From 487b6f0f8fb1d6a8d3ded9110021b36af7f5629f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 12:18:05 -0400 Subject: [PATCH 001/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.6.2 to 0.7.0 (#1584) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.6.2 to 0.7.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.6.2&new-version=0.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 04293b2404..e890652180 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.9.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.6.2 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.7.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 ) diff --git a/go.sum b/go.sum index 9d447abbe1..bb9916d011 100644 --- a/go.sum +++ b/go.sum @@ -1966,8 +1966,8 @@ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.6.2 h1:9vsKWUUg5ZPrgx1OTvuJ+tbXU5zt2nOhEt7T1ZlmQ+U= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.6.2/go.mod h1:QFx8YimjDv3fcvpJ1vGey5i8ZDOYmUXWAP1XV9eLVlg= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.7.0 h1:YJP+XePFQPPgsFITSXSQUj9k1rQ3x+e3qDG/F+pil5E= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.7.0/go.mod h1:V8lGsM5QG2kqfQJjZ/7AetgG66KoHGKh0lw4bq2fjUg= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= From f639dd0cb5a1f7fd16fc19d31cc4f996e5303765 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 11:50:08 -0400 Subject: [PATCH 002/448] deps: bump github.com/Microsoft/hcsshim from 0.12.9 to 0.13.0 (#1587) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.9 to 0.13.0.
Release notes

Sourced from github.com/Microsoft/hcsshim's releases.

v0.13.0

What's Changed

New Contributors

Full Changelog: https://github.com/microsoft/hcsshim/compare/v0.13.0-rc.3...v0.13.0

v0.13.0-rc.3

What's Changed

Full Changelog: https://github.com/microsoft/hcsshim/compare/v0.13.0-rc.2...v0.13.0-rc.3

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Microsoft/hcsshim&package-manager=go_modules&previous-version=0.12.9&new-version=0.13.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index e890652180..3f5b3379f3 100644 --- a/go.mod +++ b/go.mod @@ -270,7 +270,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 - github.com/Microsoft/hcsshim v0.12.9 + github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.36.3 github.com/aws/aws-sdk-go-v2/config v1.29.14 diff --git a/go.sum b/go.sum index bb9916d011..69a7bf0312 100644 --- a/go.sum +++ b/go.sum @@ -180,8 +180,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= -github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= +github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA= +github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok= 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/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= @@ -1193,8 +1193,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opencontainers/runc v1.2.0-rc.1 h1:SMjop2pxxYRTfKdsigna/8xRoaoCfIQfD2cVuOb64/o= -github.com/opencontainers/runc v1.2.0-rc.1/go.mod h1:m9JwxfHzXz5YTTXBQr7EY9KTuazFAGPyMQx2nRR3vTw= +github.com/opencontainers/runc v1.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19oYB80= +github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= From 3cfeac48adc91e295bb249dbb3063f8c70047c47 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 8 May 2025 18:03:54 +0200 Subject: [PATCH 003/448] feat: additional apiserver IPs from service and endpoint (#1573) # Description In some cases the flows incorrectly assumed APIServer IPs as world. This PR adds functionality to the watcher to extract IPs from the Kubernetes service and endpoints. In some managed Kubernetes offerings these IPs are used to establish connections from and to the kube-apiserver. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ![image](https://github.com/user-attachments/assets/47319020-c030-4f33-9cdd-1cded2daccd6) Before: ![image](https://github.com/user-attachments/assets/8e7a80f7-8715-47ba-9728-fc9d18cd550f) After: ![image](https://github.com/user-attachments/assets/d9ba7efa-3eac-4506-9467-fa1ba8063549) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Lukas Hoehl --- pkg/k8s/apiserver_linux.go | 10 ++-- pkg/watchers/apiserver/apiserver.go | 62 ++++++++++++++++++++++++ pkg/watchers/apiserver/apiserver_test.go | 37 ++++++++++++++ 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/pkg/k8s/apiserver_linux.go b/pkg/k8s/apiserver_linux.go index f766073a7a..22ae30c060 100644 --- a/pkg/k8s/apiserver_linux.go +++ b/pkg/k8s/apiserver_linux.go @@ -54,14 +54,12 @@ func (a *APIServerEventHandler) handleAPIServerEvent(event interface{}) { _, err := a.c.Upsert(ip.String(), nil, 0, nil, ipcache.Identity{ID: identity.ReservedIdentityKubeAPIServer, Source: source.Kubernetes}) if err != nil { a.l.WithError(err).WithFields(logrus.Fields{ - "IP": ips[0].String(), + "IP": ip.String(), }).Error("Failed to add API server IPs to ipcache") return } } - a.l.WithFields(logrus.Fields{ - "IP": ips[0].String(), - }).Info("Added API server IPs to ipcache") + a.l.Infof("Added API server IPs %v to ipcache", ips) case cc.EventTypeDeleteAPIServerIPs: apiserverObj, ok := cacheEvent.Obj.(*common.APIServerObject) if !ok { @@ -77,9 +75,7 @@ func (a *APIServerEventHandler) handleAPIServerEvent(event interface{}) { //nolint:staticcheck // TODO(timraymond): unclear how to migrate this a.c.Delete(ip.String(), source.Kubernetes) } - a.l.WithFields(logrus.Fields{ - "IP": ips[0].String(), - }).Info("Deleted API server IPs from ipcache") + a.l.Infof("Deleted API server IPs %v from ipcache", ips) default: a.l.WithFields(logrus.Fields{ "Cache Event": cacheEvent, diff --git a/pkg/watchers/apiserver/apiserver.go b/pkg/watchers/apiserver/apiserver.go index 606c2cde74..f047276bef 100644 --- a/pkg/watchers/apiserver/apiserver.go +++ b/pkg/watchers/apiserver/apiserver.go @@ -17,7 +17,10 @@ import ( "github.com/microsoft/retina/pkg/pubsub" "github.com/microsoft/retina/pkg/utils" "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" + kclient "sigs.k8s.io/controller-runtime/pkg/client" kcfg "sigs.k8s.io/controller-runtime/pkg/client/config" ) @@ -35,6 +38,7 @@ type ApiServerWatcher struct { hostResolver IHostResolver filterManager fm.IFilterManager restConfig *rest.Config + client kclient.Client } var a *ApiServerWatcher @@ -79,6 +83,15 @@ func (a *ApiServerWatcher) Init(ctx context.Context) error { a.restConfig = config } + if a.client == nil { + c, err := kclient.New(a.restConfig, kclient.Options{}) + if err != nil { + a.l.Error("failed to create kubernetes client", zap.Error(err)) + return fmt.Errorf("failed to create kubernetes client: %w", err) + } + a.client = c + } + hostName, err := a.getHostName() if err != nil { a.l.Error("failed to get host name", zap.Error(err)) @@ -149,11 +162,24 @@ func (a *ApiServerWatcher) Refresh(ctx context.Context) error { } func (a *ApiServerWatcher) initNewCache(ctx context.Context) error { + svcIPs, err := a.ipsFromService(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve ips from kubernetes service: %w", err) + } + + endpointIPs, err := a.ipsFromEndpoint(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve ips from kubernetes endpoint: %w", err) + } + ips, err := a.resolveIPs(ctx, a.apiServerHostName) if err != nil { return fmt.Errorf("failed to resolve IPs: %w", err) } + ips = append(ips, endpointIPs...) + ips = append(ips, svcIPs...) + // Reset new cache. a.new = make(cache) for _, ip := range ips { @@ -210,6 +236,42 @@ func (a *ApiServerWatcher) resolveIPs(ctx context.Context, host string) ([]strin return hostIPs, nil } +// ipsFromService retrieves IP addresses from the master service "kubernetes" in the default namespace. +// These IPs are used as a virtual-ip to the kube-apiserver. +func (a *ApiServerWatcher) ipsFromService(ctx context.Context) ([]string, error) { + svc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubernetes", + Namespace: "default", + }, + } + if err := a.client.Get(ctx, kclient.ObjectKeyFromObject(svc), svc); err != nil { + return nil, fmt.Errorf("retrieving kubernetes service: %w", err) + } + return svc.Spec.ClusterIPs, nil +} + +// ipsFromEndpoint retrieves IP addresses from the Endpoint resource "kubernetes" in the default namespace. +// These IPs are the addresses for the kube-apiserver. +func (a *ApiServerWatcher) ipsFromEndpoint(ctx context.Context) ([]string, error) { + ep := &corev1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubernetes", + Namespace: "default", + }, + } + if err := a.client.Get(ctx, kclient.ObjectKeyFromObject(ep), ep); err != nil { + return nil, fmt.Errorf("retrieving kubernetes endpoint: %w", err) + } + ips := []string{} + for _, subset := range ep.Subsets { + for _, addr := range subset.Addresses { + ips = append(ips, addr.IP) + } + } + return ips, nil +} + func (a *ApiServerWatcher) publish(netIPs []net.IP, eventType cc.EventType) { if len(netIPs) == 0 { return diff --git a/pkg/watchers/apiserver/apiserver_test.go b/pkg/watchers/apiserver/apiserver_test.go index 04105e85c1..24d7748d71 100644 --- a/pkg/watchers/apiserver/apiserver_test.go +++ b/pkg/watchers/apiserver/apiserver_test.go @@ -18,7 +18,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client/fake" ) var errDNS = errors.New("DNS error") @@ -78,6 +83,7 @@ func TestRefresh(t *testing.T) { l: log.Logger().Named("apiserver-watcher"), hostResolver: mockedResolver, filterManager: mockedFilterManager, + client: getMockKubeClient(), } // Return 2 random IPs for the host everytime LookupHost is called. @@ -132,6 +138,7 @@ func TestRefreshLookUpAlwaysFail(t *testing.T) { a := &ApiServerWatcher{ l: log.Logger().Named("apiserver-watcher"), hostResolver: mockedResolver, + client: getMockKubeClient(), } mockedResolver.EXPECT().LookupHost(gomock.Any(), gomock.Any()).Return(nil, errors.New("Error")).AnyTimes() @@ -155,6 +162,7 @@ func TestInitWithIncorrectURL(t *testing.T) { l: log.Logger().Named("apiserver-watcher"), hostResolver: mockedResolver, restConfig: getMockConfig(false), + client: getMockKubeClient(), filterManager: mockedFilterManager, } @@ -178,6 +186,34 @@ func getMockConfig(isCorrect bool) *rest.Config { } } +func getMockKubeClient() client.Client { + kubernetesSvc := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubernetes", + Namespace: "default", + }, + Spec: corev1.ServiceSpec{ + ClusterIPs: []string{"172.0.16.1"}, + }, + } + + ep := corev1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubernetes", + Namespace: "default", + }, + Subsets: []corev1.EndpointSubset{ + { + Addresses: []corev1.EndpointAddress{ + {IP: "100.64.83.200"}, + {IP: "100.64.83.201"}, + }, + }, + }, + } + return fake.NewFakeClient(&ep, &kubernetesSvc) +} + func TestRefreshFailsFirstFourAttemptsSucceedsOnFifth(t *testing.T) { _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) require.NoError(t, err) @@ -194,6 +230,7 @@ func TestRefreshFailsFirstFourAttemptsSucceedsOnFifth(t *testing.T) { l: log.Logger().Named("apiserver-watcher"), hostResolver: mockedResolver, filterManager: mockedFilterManager, + client: getMockKubeClient(), } // Simulate LookupHost failing the first four times and succeeding on the fifth. From ff856081da9595e84d61d01f57ac9c62c6fadef1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 12:04:19 -0400 Subject: [PATCH 004/448] deps: bump actions/setup-go from 5.4.0 to 5.5.0 (#1586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.4.0 to 5.5.0.
Release notes

Sourced from actions/setup-go's releases.

v5.5.0

What's Changed

Bug fixes:

Dependency updates:

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v5...v5.5.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=5.4.0&new-version=5.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 12 ++++++------ .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-images.yaml | 10 +++++----- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index bc94b24d7b..48f54d664c 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup go if: env.IS_NOT_MERGE_GROUP - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - name: Initialize CodeQL diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 8d1028594b..43d7546aec 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -89,7 +89,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 95cb3cf847..adad41005d 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,7 +24,7 @@ jobs: if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 if: env.IS_NOT_MERGE_GROUP with: go-version-file: go.mod diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 8b69aa3de6..47820d82bf 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -18,7 +18,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - name: Run GoReleaser build @@ -37,7 +37,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - name: Run GoReleaser release diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 541cfbbaa1..dbf20a09f2 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -25,7 +25,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -76,7 +76,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -128,7 +128,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -178,7 +178,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -227,7 +227,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -313,7 +313,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index d202b45148..b5eb02ba6e 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -51,7 +51,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 302a334590..3a3bd417d0 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -26,7 +26,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -72,7 +72,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -118,7 +118,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -163,7 +163,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version @@ -206,7 +206,7 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index f46db14bae..509c1bc063 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -71,7 +71,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 98c40277d7..358368754b 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9144fa6c03..42c74c944b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod From 7e2fc3346eaabf3ece23c1d181a1de7dcac2bd82 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 9 May 2025 07:07:51 +0100 Subject: [PATCH 005/448] feat(conntrack-metrics): legacy control plane basic mode (#1253) # Description Initial implementation of conntrack metrics for the legacy control plane in basic mode. The aggregation is at the node level, which makes the metric bounded. Metrics: - conntrack_bytes_tx - conntrack_bytes_rx - conntrack_packets_tx - conntrack_packets_rx - conntrack_total_connections ## Related Issue fixes https://github.com/microsoft/retina/issues/1190 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/contributing). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Bytes RX ![image](https://github.com/user-attachments/assets/4e79109c-406c-47b7-b426-95003ecfdc64) Total connections metric ![image](https://github.com/user-attachments/assets/f3759fd8-6d8f-4301-b4e0-c8f01a74d539) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/metrics/metrics.go | 30 +++++++++++++++++ pkg/metrics/types.go | 14 ++++++++ pkg/plugin/conntrack/_cprog/conntrack.c | 32 +++++++++--------- pkg/plugin/conntrack/conntrack_bpfel_arm64.go | 8 ++--- pkg/plugin/conntrack/conntrack_bpfel_x86.go | 8 ++--- pkg/plugin/conntrack/conntrack_linux.go | 33 +++++++++++++++++++ .../packetparser/packetparser_bpfel_arm64.go | 16 ++++----- .../packetparser/packetparser_bpfel_x86.go | 16 ++++----- pkg/utils/metric_names.go | 7 ++++ 9 files changed, 124 insertions(+), 40 deletions(-) diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 190ae2360f..ea9e2e5a9d 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -158,6 +158,36 @@ func InitializeMetrics() { utils.InterfaceName, ) + ConntrackPacketsTx = exporter.CreatePrometheusGaugeVecForMetric( + exporter.DefaultRegistry, + utils.ConntrackPacketsTxGaugeName, + ConntrackPacketTxDescription, + ) + + ConntrackPacketsRx = exporter.CreatePrometheusGaugeVecForMetric( + exporter.DefaultRegistry, + utils.ConntrackPacketsRxGaugeName, + ConntrackPacketRxDescription, + ) + + ConntrackBytesTx = exporter.CreatePrometheusGaugeVecForMetric( + exporter.DefaultRegistry, + utils.ConntrackBytesTxGaugeName, + ConntrackBytesTxDescription, + ) + + ConntrackBytesRx = exporter.CreatePrometheusGaugeVecForMetric( + exporter.DefaultRegistry, + utils.ConntrackBytesRxGaugeName, + ConntrackBytesRxDescription, + ) + + ConntrackTotalConnections = exporter.CreatePrometheusGaugeVecForMetric( + exporter.DefaultRegistry, + utils.ConntrackTotalConnectionsName, + ConntrackTotalConnectionsDescription, + ) + isInitialized = true metricsLogger.Info("Metrics initialized") } diff --git a/pkg/metrics/types.go b/pkg/metrics/types.go index 562d8612e7..486698390a 100644 --- a/pkg/metrics/types.go +++ b/pkg/metrics/types.go @@ -43,6 +43,13 @@ const ( // Control plane metrics pluginManagerFailedToReconcileCounterDescription = "Number of times the plugin manager failed to reconcile the plugins" lostEventsCounterDescription = "Number of events lost in control plane" + + // Conntrack metrics + ConntrackPacketTxDescription = "Number of tx packets" + ConntrackPacketRxDescription = "Number of rx packets" + ConntrackBytesTxDescription = "Number of tx bytes" + ConntrackBytesRxDescription = "Number of rx bytes" + ConntrackTotalConnectionsDescription = "Total number of connections" ) // Metric Counters @@ -90,6 +97,13 @@ var ( InfinibandStatsGauge GaugeVec InfinibandStatusParamsGauge GaugeVec + + // Conntrack + ConntrackPacketsTx GaugeVec + ConntrackPacketsRx GaugeVec + ConntrackBytesTx GaugeVec + ConntrackBytesRx GaugeVec + ConntrackTotalConnections GaugeVec ) func ToPrometheusType(metric interface{}) prometheus.Collector { diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c index ffc7fd34f6..a86cf49bab 100644 --- a/pkg/plugin/conntrack/_cprog/conntrack.c +++ b/pkg/plugin/conntrack/_cprog/conntrack.c @@ -21,14 +21,14 @@ struct conntrackmetadata { bytes_*_count indicates the number of bytes sent and received in the forward and reply direction. These values will be based on the conntrack entry. */ - __u64 bytes_forward_count; - __u64 bytes_reply_count; + __u64 bytes_tx_count; + __u64 bytes_rx_count; /* packets_*_count indicates the number of packets sent and received in the forward and reply direction. These values will be based on the conntrack entry. */ - __u32 packets_forward_count; - __u32 packets_reply_count; + __u32 packets_tx_count; + __u32 packets_rx_count; }; struct packet @@ -145,8 +145,8 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru new_value.traffic_direction = _ct_get_traffic_direction(observation_point); #ifdef ENABLE_CONNTRACK_METRICS - new_value.conntrack_metadata.packets_forward_count = 1; - new_value.conntrack_metadata.bytes_forward_count = p->bytes; + new_value.conntrack_metadata.packets_tx_count = 1; + new_value.conntrack_metadata.bytes_tx_count = p->bytes; // Update initial conntrack metadata for the connection. __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS @@ -177,8 +177,8 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c new_value.last_report_tx_dir = now; new_value.traffic_direction = _ct_get_traffic_direction(observation_point); #ifdef ENABLE_CONNTRACK_METRICS - new_value.conntrack_metadata.packets_forward_count = 1; - new_value.conntrack_metadata.bytes_forward_count = p->bytes; + new_value.conntrack_metadata.packets_tx_count = 1; + new_value.conntrack_metadata.bytes_tx_count = p->bytes; // Update packet's conntrack metadata. __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));; #endif // ENABLE_CONNTRACK_METRICS @@ -226,8 +226,8 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c new_value.flags_seen_rx_dir = p->flags; new_value.last_report_rx_dir = now; #ifdef ENABLE_CONNTRACK_METRICS - new_value.conntrack_metadata.bytes_reply_count = p->bytes; - new_value.conntrack_metadata.packets_reply_count = 1; + new_value.conntrack_metadata.bytes_rx_count = p->bytes; + new_value.conntrack_metadata.packets_rx_count = 1; #endif // ENABLE_CONNTRACK_METRICS bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY); } else { // Otherwise, the packet is considered as a packet in the send direction. @@ -235,8 +235,8 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c new_value.flags_seen_tx_dir = p->flags; new_value.last_report_tx_dir = now; #ifdef ENABLE_CONNTRACK_METRICS - new_value.conntrack_metadata.bytes_forward_count = p->bytes; - new_value.conntrack_metadata.packets_forward_count = 1; + new_value.conntrack_metadata.bytes_tx_count = p->bytes; + new_value.conntrack_metadata.packets_tx_count = 1; #endif // ENABLE_CONNTRACK_METRICS bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY); } @@ -400,8 +400,8 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac p->traffic_direction = entry->traffic_direction; #ifdef ENABLE_CONNTRACK_METRICS // Update packet count and bytes count on conntrack entry. - WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1); - WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes); + WRITE_ONCE(entry->conntrack_metadata.packets_tx_count, READ_ONCE(entry->conntrack_metadata.packets_tx_count) + 1); + WRITE_ONCE(entry->conntrack_metadata.bytes_tx_count, READ_ONCE(entry->conntrack_metadata.bytes_tx_count) + p->bytes); // Update packet's conntract metadata. __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS @@ -422,8 +422,8 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac p->traffic_direction = entry->traffic_direction; #ifdef ENABLE_CONNTRACK_METRICS // Update packet count and bytes count on conntrack entry. - WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1); - WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes); + WRITE_ONCE(entry->conntrack_metadata.packets_rx_count, READ_ONCE(entry->conntrack_metadata.packets_rx_count) + 1); + WRITE_ONCE(entry->conntrack_metadata.bytes_rx_count, READ_ONCE(entry->conntrack_metadata.bytes_rx_count) + p->bytes); // Update packet's conntract metadata. __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS diff --git a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go index efb93738a6..0cfed44cf9 100644 --- a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go +++ b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go @@ -21,10 +21,10 @@ type conntrackCtEntry struct { FlagsSeenRxDir uint8 IsDirectionUnknown bool ConntrackMetadata struct { - BytesForwardCount uint64 - BytesReplyCount uint64 - PacketsForwardCount uint32 - PacketsReplyCount uint32 + BytesTxCount uint64 + BytesRxCount uint64 + PacketsTxCount uint32 + PacketsRxCount uint32 } } diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.go b/pkg/plugin/conntrack/conntrack_bpfel_x86.go index baa46bcbfa..a3522e44de 100644 --- a/pkg/plugin/conntrack/conntrack_bpfel_x86.go +++ b/pkg/plugin/conntrack/conntrack_bpfel_x86.go @@ -21,10 +21,10 @@ type conntrackCtEntry struct { FlagsSeenRxDir uint8 IsDirectionUnknown bool ConntrackMetadata struct { - BytesForwardCount uint64 - BytesReplyCount uint64 - PacketsForwardCount uint32 - PacketsReplyCount uint32 + BytesTxCount uint64 + BytesRxCount uint64 + PacketsTxCount uint32 + PacketsRxCount uint32 } } diff --git a/pkg/plugin/conntrack/conntrack_linux.go b/pkg/plugin/conntrack/conntrack_linux.go index dc2fb0c449..4e1eb41cf3 100644 --- a/pkg/plugin/conntrack/conntrack_linux.go +++ b/pkg/plugin/conntrack/conntrack_linux.go @@ -16,6 +16,7 @@ import ( "github.com/microsoft/retina/internal/ktime" "github.com/microsoft/retina/pkg/loader" "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/metrics" plugincommon "github.com/microsoft/retina/pkg/plugin/common" _ "github.com/microsoft/retina/pkg/plugin/conntrack/_cprog" // nolint // This is needed so cprog is included when vendoring "github.com/microsoft/retina/pkg/utils" @@ -23,6 +24,8 @@ import ( "go.uber.org/zap" ) +var conntrackMetricsEnabled = false // conntrack metrics global variable + //go:generate go run github.com/cilium/ebpf/cmd/bpf2go@master -cflags "-g -O2 -Wall -D__TARGET_ARCH_${GOARCH} -Wall" -target ${GOARCH} -type ct_v4_key conntrack ./_cprog/conntrack.c -- -I../lib/_${GOARCH} -I../lib/common/libbpf/_src -I../lib/common/libbpf/_include/linux -I../lib/common/libbpf/_include/uapi/linux -I../lib/common/libbpf/_include/asm // Init initializes the conntrack eBPF map in the kernel for the first time. @@ -88,6 +91,10 @@ func GenerateDynamic(ctx context.Context, dynamicHeaderPath string, conntrackMet if err != nil { return errors.Wrap(err, "failed to write conntrack dynamic header") } + // set a global variable + if conntrackMetrics == 1 { + conntrackMetricsEnabled = true + } return nil } @@ -118,6 +125,10 @@ func (ct *Conntrack) Run(ctx context.Context) error { // List of keys to be deleted var keysToDelete []conntrackCtV4Key + // metrics counters + var packetsCountTx, packetsCountRx, totConnections uint32 + var bytesCountTx, bytesCountRx uint64 + iter := ct.ctMap.Iterate() for iter.Next(&key, &value) { noOfCtEntries++ @@ -133,6 +144,18 @@ func (ct *Conntrack) Run(ctx context.Context) error { dstIP := utils.Int2ip(key.DstIp).To4() sourcePortShort := uint32(utils.HostToNetShort(key.SrcPort)) destinationPortShort := uint32(utils.HostToNetShort(key.DstPort)) + + // Add conntrack metrics. + if conntrackMetricsEnabled { + // Basic metrics, node-level + ctMeta := value.ConntrackMetadata + totConnections++ + bytesCountTx += ctMeta.BytesTxCount + bytesCountRx += ctMeta.BytesRxCount + packetsCountTx += ctMeta.PacketsTxCount + packetsCountRx += ctMeta.PacketsRxCount + } + ct.l.Debug("conntrack entry", zap.String("src_ip", srcIP.String()), zap.Uint32("src_port", sourcePortShort), @@ -151,6 +174,16 @@ func (ct *Conntrack) Run(ctx context.Context) error { if err := iter.Err(); err != nil { ct.l.Error("Iterate failed", zap.Error(err)) } + + // create metrics + if conntrackMetricsEnabled { + metrics.ConntrackPacketsTx.WithLabelValues().Set(float64(packetsCountTx)) + metrics.ConntrackBytesTx.WithLabelValues().Set(float64(bytesCountTx)) + metrics.ConntrackPacketsRx.WithLabelValues().Set(float64(packetsCountRx)) + metrics.ConntrackBytesRx.WithLabelValues().Set(float64(bytesCountRx)) + metrics.ConntrackTotalConnections.WithLabelValues().Set(float64(totConnections)) + } + // Delete the conntrack entries for _, key := range keysToDelete { if err := ct.ctMap.Delete(key); err != nil { diff --git a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go index ebfa05e37f..df05ffdcac 100644 --- a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go +++ b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go @@ -21,10 +21,10 @@ type packetparserCtEntry struct { FlagsSeenRxDir uint8 IsDirectionUnknown bool ConntrackMetadata struct { - BytesForwardCount uint64 - BytesReplyCount uint64 - PacketsForwardCount uint32 - PacketsReplyCount uint32 + BytesTxCount uint64 + BytesRxCount uint64 + PacketsTxCount uint32 + PacketsRxCount uint32 } } @@ -62,10 +62,10 @@ type packetparserPacket struct { IsReply bool _ [3]byte ConntrackMetadata struct { - BytesForwardCount uint64 - BytesReplyCount uint64 - PacketsForwardCount uint32 - PacketsReplyCount uint32 + BytesTxCount uint64 + BytesRxCount uint64 + PacketsTxCount uint32 + PacketsRxCount uint32 } } diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.go b/pkg/plugin/packetparser/packetparser_bpfel_x86.go index 36de41247b..321f836b0e 100644 --- a/pkg/plugin/packetparser/packetparser_bpfel_x86.go +++ b/pkg/plugin/packetparser/packetparser_bpfel_x86.go @@ -21,10 +21,10 @@ type packetparserCtEntry struct { FlagsSeenRxDir uint8 IsDirectionUnknown bool ConntrackMetadata struct { - BytesForwardCount uint64 - BytesReplyCount uint64 - PacketsForwardCount uint32 - PacketsReplyCount uint32 + BytesTxCount uint64 + BytesRxCount uint64 + PacketsTxCount uint32 + PacketsRxCount uint32 } } @@ -62,10 +62,10 @@ type packetparserPacket struct { IsReply bool _ [3]byte ConntrackMetadata struct { - BytesForwardCount uint64 - BytesReplyCount uint64 - PacketsForwardCount uint32 - PacketsReplyCount uint32 + BytesTxCount uint64 + BytesRxCount uint64 + PacketsTxCount uint32 + PacketsRxCount uint32 } } diff --git a/pkg/utils/metric_names.go b/pkg/utils/metric_names.go index 8060b05243..5bb7f280d3 100644 --- a/pkg/utils/metric_names.go +++ b/pkg/utils/metric_names.go @@ -34,6 +34,13 @@ const ( // Common Gauges across os distributions NodeConnectivityStatusName = "node_connectivity_status" NodeConnectivityLatencySecondsName = "node_connectivity_latency_seconds" + + // Conntrack + ConntrackPacketsTxGaugeName = "conntrack_packets_tx" + ConntrackPacketsRxGaugeName = "conntrack_packets_rx" + ConntrackBytesTxGaugeName = "conntrack_bytes_tx" + ConntrackBytesRxGaugeName = "conntrack_bytes_rx" + ConntrackTotalConnectionsName = "conntrack_total_connections" ) // IsAdvancedMetric is a helper function to determine if a name is an advanced metric From 76f74c6050d189149367bf97abcbb07837b38b0b Mon Sep 17 00:00:00 2001 From: Ritwik Ranjan Date: Mon, 12 May 2025 18:39:31 +0300 Subject: [PATCH 006/448] deps: bump github.com/safchain/ethtool from v0.5.10 to v0.6.0 (#1594) # Description This pull request updates the version of the `ethtool` dependency in the `go.mod` file to ensure compatibility with the latest fixes. With go version upgrade from 1.23 to 1.24, certain behavior of go with relation memory management got changed (see https://github.com/golang/go/issues/73536) which effected out linuxutil plugin leading to a jump in memory usage. With the help of pprof profiling we identified the root cause in ethtool library (see https://github.com/golang/go/issues/73536). The ethtool lib owners implemented a change to address the issue which was released with tag `v0.6.0`. Dependency update: * [`go.mod`](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L300-R300): Updated the `github.com/safchain/ethtool` dependency from version `v0.5.10` to `v0.6.0`. ## Screenshots (if applicable) or Testing Completed I ran retina with a workload that was utilizing following network at around ~30% cpu: ![image](https://github.com/user-attachments/assets/e8c74fe5-3317-4872-9543-46bd8486296b) Here is the memory profile while running different versions of retina, the last one is this commit. ![image](https://github.com/user-attachments/assets/bfd399e0-1ded-44d6-95e6-8830c6181c05) While we don't come back to original level, we do see an improvement in memory usage of around ~10% --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 3f5b3379f3..25c1a0e859 100644 --- a/go.mod +++ b/go.mod @@ -297,7 +297,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.63.0 - github.com/safchain/ethtool v0.5.10 + github.com/safchain/ethtool v0.6.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1-0.20250328051554-cb48698f2590 diff --git a/go.sum b/go.sum index 69a7bf0312..28da91fd31 100644 --- a/go.sum +++ b/go.sum @@ -1301,8 +1301,8 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a h1:np2nR32/A/VcOG9Hn+IOPA8kMk1gbBzK5LpSsgq5pJI= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a/go.mod h1:wiP6GQ2T378F+YIyuNw7yXtBxJZR+fqrrn1Z6UHZi0Q= -github.com/safchain/ethtool v0.5.10 h1:Im294gZtuf4pSGJRAOGKaASNi3wMeFaGaWuSaomedpc= -github.com/safchain/ethtool v0.5.10/go.mod h1:w9jh2Lx7YBR4UwzLkzCmWl85UY0W2uZdd7/DckVE5+c= +github.com/safchain/ethtool v0.6.0 h1:38VicU4p9ewEQFLemCFiGsknSMn7S3xXEzxaGYTjcn4= +github.com/safchain/ethtool v0.6.0/go.mod h1:JzoNbG8xeg/BeVeVoMCtCb3UPWoppZZbFpA+1WFh+M0= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= @@ -1772,7 +1772,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From 9510b0493cf6d09ba5db9e6ed53f181eb022aef4 Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Mon, 12 May 2025 10:15:43 -0700 Subject: [PATCH 007/448] fix: include Mariner check for Hubble scenario (#1588) Fixes https://github.com/microsoft/retina/pull/1458 In the PR above, I only added the `/etc/host-os-release` volumeMount in `deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml` but not in `deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml` The omission was because in the former we iterate over the volume mount list defined in values.yaml, while the latter defines them explicitly in the daemonset. --- .../controller/helm/retina/templates/agent/daemonset.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml index 5dd90331a4..cdb14ed2c5 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml @@ -120,6 +120,8 @@ spec: mountPath: /sys/kernel/tracing - name: cilium mountPath: /var/run/cilium + - name: host-os-release + mountPath: /etc/os-release {{- if .Values.hubble.tls.enabled }} - name: tls mountPath: /var/lib/cilium/tls/hubble @@ -146,6 +148,10 @@ spec: hostPath: path: /var/run/cilium type: DirectoryOrCreate + - name: host-os-release + hostPath: + path: /etc/os-release + type: FileOrCreate {{- if .Values.hubble.tls.enabled }} - name: tls projected: From 9e89dd999d256243c8cd3555f585da7857b4d1b0 Mon Sep 17 00:00:00 2001 From: Tim Kang Date: Tue, 13 May 2025 02:47:13 +0900 Subject: [PATCH 008/448] fix(controller): add warning for nodes with no addresses in reconciliation (#1569) # Description This PR improves the `NodeReconciler` logic in `controller.go` by adding a safeguard for nodes with no addresses. Specifically, it ensures that if a node has an empty `Status.Addresses` field, a warning is logged, and the reconciliation process exits gracefully without further processing. This prevents potential runtime errors when attempting to access an address that does not exist. ## Related Issue resolve #1541 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed The following scenarios were tested: 1. **Node with no addresses**: Verified that a warning is logged, and the reconciliation exits without errors. 2. **Node with valid addresses**: Verified that the `RetinaNode` is created and updated in the cache correctly. 3. **Node being deleted**: Verified that the `RetinaNode` is removed from the cache as expected. All tests passed successfully. ## Additional Notes This change ensures that the `NodeReconciler` handles edge cases more robustly, improving the stability of the controller. The added safeguard prevents potential issues when interacting with nodes that lack address information. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/controllers/daemon/node/controller.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/controllers/daemon/node/controller.go b/pkg/controllers/daemon/node/controller.go index 60221106c4..cdc48486ea 100644 --- a/pkg/controllers/daemon/node/controller.go +++ b/pkg/controllers/daemon/node/controller.go @@ -75,6 +75,11 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. return ctrl.Result{}, nil } + if len(node.Status.Addresses) == 0 { + r.l.Warn("Node has no addresses", zap.String("Node", req.NamespacedName.String())) + return ctrl.Result{}, nil + } + retinaNodeCommon := retinaCommon.NewRetinaNode(node.Name, net.ParseIP(node.Status.Addresses[0].Address)) if err := r.cache.UpdateRetinaNode(retinaNodeCommon); err != nil { r.l.Error("Failed to update RetinaNode in Cache", zap.Error(err), zap.String("Node", req.NamespacedName.String())) From 6a8910056736107b8573bc1779bff49f320b8c01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 13:55:43 -0400 Subject: [PATCH 009/448] deps: bump github.com/vishvananda/netlink from 1.3.1-0.20250328051554-cb48698f2590 to 1.3.1 (#1592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.3.1-0.20250328051554-cb48698f2590 to 1.3.1.
Release notes

Sourced from github.com/vishvananda/netlink's releases.

v1.3.1

What's Changed

New Contributors

Full Changelog: https://github.com/vishvananda/netlink/compare/v1.3.0...v1.3.1

What's Changed

... (truncated)

Commits

Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | github.com/vishvananda/netlink | [< 1.3, > 1.2.1-beta.2.0.20240524165444-4d4ba1473f21] |
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/vishvananda/netlink&package-manager=go_modules&previous-version=1.3.1-0.20250328051554-cb48698f2590&new-version=1.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 25c1a0e859..3b4e0dcffc 100644 --- a/go.mod +++ b/go.mod @@ -300,7 +300,7 @@ require ( github.com/safchain/ethtool v0.6.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 - github.com/vishvananda/netlink v1.3.1-0.20250328051554-cb48698f2590 + github.com/vishvananda/netlink v1.3.1 go.opentelemetry.io/otel v1.35.0 go.opentelemetry.io/otel/metric v1.35.0 go.opentelemetry.io/otel/trace v1.35.0 diff --git a/go.sum b/go.sum index 28da91fd31..0957e2c27c 100644 --- a/go.sum +++ b/go.sum @@ -1454,8 +1454,8 @@ github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vishvananda/netlink v1.3.1-0.20250328051554-cb48698f2590 h1:vlb3S673iuHRrc359PkZ5ASE4J1vfRj0ti4g+jkNOWI= -github.com/vishvananda/netlink v1.3.1-0.20250328051554-cb48698f2590/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20220614130704-4b1c25a33c7c h1:gFwUKtkv6QzQsFdIjvPqd0Qdw42DHUEbbUdiUTI1uco= From 4cc4f6b0151328b1763b4d52a57ac8f958635526 Mon Sep 17 00:00:00 2001 From: Younsung Lee Date: Tue, 13 May 2025 12:49:52 +0900 Subject: [PATCH 010/448] feat(helm): Add resources.requests for retina-agent (#1595) # Description - In certain cases, cluster admins must be able to directly modify resources.requests to bypass pending issues with the retina-agent DaemonSet. - Recommit 90a370f20b5c20c360caa7e70bd0572f9cb2c79a due to gpg-signing PR #1589 (Requested by @nddq) ## Related Issue Reopen from #1589 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: younsl --- .../controller/helm/retina/templates/agent/daemonset.yaml | 3 +++ deploy/hubble/manifests/controller/helm/retina/values.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml index cdb14ed2c5..f9bed3a751 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml @@ -75,6 +75,9 @@ spec: ports: - containerPort: {{ .Values.agent.container.retina.ports.containerPort }} resources: + requests: + memory: {{ .Values.resources.requests.memory | quote }} + cpu: {{ .Values.resources.requests.cpu | quote }} limits: memory: {{ .Values.resources.limits.memory | quote }} cpu: {{ .Values.resources.limits.cpu | quote }} diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index e68d8c82b0..31415a1d32 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -130,6 +130,9 @@ serviceAccount: name: "retina-agent" resources: + requests: + memory: "500Mi" + cpu: "500m" limits: memory: "500Mi" cpu: "500m" From e7726ae2cfa2704099dc09d286a49a940091621b Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Tue, 13 May 2025 15:42:46 -0700 Subject: [PATCH 011/448] feat: add is_reply label to advanced packet forward metrics (#1556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Adds the `is_reply` label to advanced packet forward metrics. Optional as part of the `MetricsConfiguration`. ## Related Issue https://github.com/microsoft/retina/issues/1426 ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Screenshot 2025-04-23 at 2 49 22 PM # Exported metrics without `is_reply` in the `MetricsConfiguration` ``` networkobservability_adv_forward_bytes{destination_ip="10.128.45.3",destination_namespace="unknown",destination_podname="unknown",direction="EGRESS",source_ip="172.18.7.2",source_namespace="platform-logging",source_podname="fluentd-58c5q"} 54 networkobservability_adv_forward_bytes{destination_ip="10.128.45.3",destination_namespace="unknown",destination_podname="unknown",direction="INGRESS",source_ip="172.18.7.2",source_namespace="platform-logging",source_podname="fluentd-58c5q"} 726 ``` # Exported metrics with `is_reply` in the `MetricsConfiguration` `additionalLabels` ``` networkobservability_adv_forward_bytes{destination_ip="10.128.45.3",destination_namespace="unknown",destination_podname="unknown",direction="INGRESS",is_reply="false",source_ip="172.18.7.2",source_namespace="platform-logging",source_podname="fluentd-58c5q"} 54 networkobservability_adv_forward_bytes{destination_ip="10.128.45.3",destination_namespace="unknown",destination_podname="unknown",direction="INGRESS",is_reply="true",source_ip="172.18.7.1",source_namespace="kube-system",source_podname="ebs-csi-node-5qmwq"} 950 networkobservability_adv_forward_bytes{destination_ip="10.128.45.3",destination_namespace="unknown",destination_podname="unknown",direction="INGRESS",is_reply="true",source_ip="172.18.7.2",source_namespace="platform-logging",source_podname="fluentd-58c5q"} 672 ``` --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- pkg/module/metrics/forward.go | 10 ++++++++-- pkg/module/metrics/forward_test.go | 27 +++++++++++++++++++++++++++ pkg/utils/attr_utils.go | 1 + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/pkg/module/metrics/forward.go b/pkg/module/metrics/forward.go index 7263ed0b7c..5044ab4c1c 100644 --- a/pkg/module/metrics/forward.go +++ b/pkg/module/metrics/forward.go @@ -4,6 +4,8 @@ package metrics import ( + "slices" + "strconv" "strings" v1 "github.com/cilium/cilium/api/v1/flow" @@ -83,7 +85,9 @@ func (f *ForwardMetrics) getLabels() []string { f.l.Info("dst labels", zap.Any("labels", labels)) } - // No additional context options + if slices.Contains(f.ctxOptions.AdditionalLabels, utils.IsReply) { + labels = append(labels, utils.IsReply) + } return labels } @@ -135,7 +139,9 @@ func (f *ForwardMetrics) ProcessFlow(flow *v1.Flow) { } } - // No additional context options + if slices.Contains(f.ctxOptions.AdditionalLabels, utils.IsReply) { + labels = append(labels, strconv.FormatBool(flow.GetIsReply().GetValue())) + } f.update(flow, labels) f.l.Debug("forward count metric is added", zap.Any("labels", labels)) diff --git a/pkg/module/metrics/forward_test.go b/pkg/module/metrics/forward_test.go index 9d48f30577..1af7558483 100644 --- a/pkg/module/metrics/forward_test.go +++ b/pkg/module/metrics/forward_test.go @@ -275,6 +275,33 @@ func TestNewForward(t *testing.T) { metricCall: 2, localContext: localContext, }, + { + name: "src and dest opts 1 with flow in local context and is_reply", + opts: &v1alpha1.MetricsContextOptions{ + MetricName: "FORWARD", + SourceLabels: []string{"ip", "namespace", "podName", "Workload", "PORT", "serVICE"}, + AdditionalLabels: []string{"is_reply"}, + }, + f: &flow.Flow{ + Verdict: flow.Verdict_FORWARDED, + Destination: &flow.Endpoint{}, + Source: &flow.Endpoint{}, + }, + checkIsAdvance: true, + exepectedLabels: []string{ + "direction", + "ip", + "namespace", + "podname", + "workload_kind", + "workload_name", + "service", + "port", + "is_reply", + }, + metricCall: 2, + localContext: localContext, + }, } for _, tc := range tt { diff --git a/pkg/utils/attr_utils.go b/pkg/utils/attr_utils.go index e5266e9b02..eac816e88f 100644 --- a/pkg/utils/attr_utils.go +++ b/pkg/utils/attr_utils.go @@ -33,6 +33,7 @@ var ( Type = "type" Reason = "reason" Direction = "direction" + IsReply = "is_reply" SourceNodeName = "source_node_name" TargetNodeName = "target_node_name" State = "state" From ba60b788257dd26dd45a3fcf80bfe4c5dae46174 Mon Sep 17 00:00:00 2001 From: Younsung Lee Date: Wed, 14 May 2025 08:47:22 +0900 Subject: [PATCH 012/448] fix(helm): Missing helper template for ingress resource (#1570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fix ingress helm template issue due to missing helper script: - The hubble-ui subchart of retina doesn't include the `ingress.paths` definition from the cilium chart, so it needs to be defined instead in the _helpers.tpl helper script of retina. - Root cause line in `ingress.yaml` template: https://github.com/microsoft/retina/blob/7e2fc3346eaabf3ece23c1d181a1de7dcac2bd82/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/ingress.yaml#L38 ## Related Issue - https://github.com/cilium/cilium/pull/13682 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Ingress completly created (screenshot from k9s): 붙여넣은_이미지_2025__4__30__오후_5_27 ## Additional Notes N/A --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: younsl --- .../helm/retina/templates/_helpers.tpl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/_helpers.tpl b/deploy/hubble/manifests/controller/helm/retina/templates/_helpers.tpl index ce25734672..36834bb3cd 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/_helpers.tpl +++ b/deploy/hubble/manifests/controller/helm/retina/templates/_helpers.tpl @@ -80,3 +80,21 @@ Return the appropriate apiVersion for cronjob. {{- print "batch/v1beta1" -}} {{- end -}} {{- end -}} + +{{/* +Return the appropriate backend for Hubble UI ingress. +*/}} +{{- define "ingress.paths" -}} +{{ if semverCompare ">=1.4-0, <1.19-0" .Capabilities.KubeVersion.Version -}} +backend: + serviceName: hubble-ui + servicePort: http +{{- else if semverCompare "^1.19-0" .Capabilities.KubeVersion.Version -}} +pathType: Prefix +backend: + service: + name: hubble-ui + port: + name: http +{{- end -}} +{{- end -}} \ No newline at end of file From 4a7621dde3c58883fa12faa95b3a752887577fc9 Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Thu, 15 May 2025 09:50:45 -0700 Subject: [PATCH 013/448] test: add FIPS-enabled Mariner node pool to E2E (#1602) Currently Retina is not FIPS-compliant across the board. This is to help validate the support matrix. --- .../framework/azure/create-cluster-with-npm.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index 731ff2051c..eb7129b007 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -81,6 +81,22 @@ func (c *CreateNPMCluster) Run() error { MaxPods: to.Ptr(int32(MaxPodsPerNode)), }) + //nolint:appendCombine // separate for verbosity + npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ + Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), + AvailabilityZones: []*string{to.Ptr("1")}, + Count: to.Ptr[int32](AuxilaryNodeCount), + EnableNodePublicIP: to.Ptr(false), + EnableFIPS: to.Ptr(true), + Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), + OSType: to.Ptr(armcontainerservice.OSTypeLinux), + OSSKU: to.Ptr(armcontainerservice.OSSKUCBLMariner), + ScaleDownMode: to.Ptr(armcontainerservice.ScaleDownModeDelete), + VMSize: to.Ptr(AgentSKU), + Name: to.Ptr("fipsmariner"), + MaxPods: to.Ptr(int32(MaxPodsPerNode)), + }) + //nolint:appendCombine // separate for verbosity npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ //nolint:all Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), From d95112aca1d286f1278a5e1909028bf1a437b8da Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Thu, 15 May 2025 15:15:37 -0700 Subject: [PATCH 014/448] fix: revert: test: add FIPS-enabled Mariner node pool to E2E (#1606) Reverting #1602 that added a stale OSSKU tag which is failing in merge queue now. This was merged due to a GH a race condition in a skipped job. Will follow-up with another PR just enabling FIPS on the existing AzureLinux node pool. --- .../framework/azure/create-cluster-with-npm.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index eb7129b007..731ff2051c 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -81,22 +81,6 @@ func (c *CreateNPMCluster) Run() error { MaxPods: to.Ptr(int32(MaxPodsPerNode)), }) - //nolint:appendCombine // separate for verbosity - npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ - Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), - AvailabilityZones: []*string{to.Ptr("1")}, - Count: to.Ptr[int32](AuxilaryNodeCount), - EnableNodePublicIP: to.Ptr(false), - EnableFIPS: to.Ptr(true), - Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), - OSType: to.Ptr(armcontainerservice.OSTypeLinux), - OSSKU: to.Ptr(armcontainerservice.OSSKUCBLMariner), - ScaleDownMode: to.Ptr(armcontainerservice.ScaleDownModeDelete), - VMSize: to.Ptr(AgentSKU), - Name: to.Ptr("fipsmariner"), - MaxPods: to.Ptr(int32(MaxPodsPerNode)), - }) - //nolint:appendCombine // separate for verbosity npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ //nolint:all Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), From d4aa7945b1fa286bd3649a9f74861ddf96e3a184 Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Thu, 15 May 2025 17:20:11 -0700 Subject: [PATCH 015/448] test: Enable FIPS using existing AzureLinux node pool. (#1609) #1602 used a stale SKU tag, and somehow slipped through the CI. Submitting this again with the up-to-date AzureLinux tag. --- test/e2e/framework/azure/create-cluster-with-npm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index 731ff2051c..ff0708c527 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -72,6 +72,7 @@ func (c *CreateNPMCluster) Run() error { AvailabilityZones: []*string{to.Ptr("1")}, Count: to.Ptr[int32](AuxilaryNodeCount), EnableNodePublicIP: to.Ptr(false), + EnableFIPS: to.Ptr(true), Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), OSType: to.Ptr(armcontainerservice.OSTypeLinux), OSSKU: to.Ptr(armcontainerservice.OSSKUAzureLinux), From a9b4371b3bf0bd5325073b3d983790fcb260ebfb Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Thu, 15 May 2025 17:54:29 -0700 Subject: [PATCH 016/448] fix(fips): Grant permissions to support FIPS on Ubuntu (#1600) When running on the FIPS-compliant Ubuntu 20.04, Retina requires `SYS_RESOURCE` on top of `IPC_LOCK`. Also, skip attaching to unavailable kernel hook points. Merge after https://github.com/microsoft/retina/pull/1601 - otherwise the pod still fails, just at a later stage. --- deploy/hubble/manifests/controller/helm/retina/values.yaml | 4 ++-- deploy/standard/manifests/controller/helm/retina/values.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 31415a1d32..360081f1a1 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -108,9 +108,9 @@ securityContext: capabilities: add: - SYS_ADMIN - - SYS_RESOURCE + - SYS_RESOURCE # for setting rlimit - NET_ADMIN # for packetparser plugin - - IPC_LOCK # for mmap() calls made by NewReader(), ref: https://man7.org/linux/man-pages/man2/mmap.2.html + - IPC_LOCK # for mmap() calls made by NewReader(), ref: https://man7.org/linux/man-pages/man2/mmap.2.html windowsOptions: runAsUserName: "NT AUTHORITY\\SYSTEM" diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index cc35bdaab8..032157e17c 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -125,6 +125,7 @@ securityContext: - SYS_ADMIN - NET_ADMIN # for packetparser plugin - IPC_LOCK # for mmap() calls made by NewReader(), ref: https://man7.org/linux/man-pages/man2/mmap.2.html + - SYS_RESOURCE # for setting rlimit windowsOptions: runAsUserName: "NT AUTHORITY\\SYSTEM" From 4f729e62981948495e936d10e379084549234591 Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Fri, 16 May 2025 08:50:41 -0700 Subject: [PATCH 017/448] fix(DropReason): Do not load fexit programs on kernels below 5.5 (#1601) In #1458 I added a kernel version check to only attach `fexit` programs when they're supported. We also need to ensure we don't even load them into the kernel. --- pkg/plugin/dropreason/dropreason_linux.go | 133 +----------- .../dropreason/dropreason_linux_test.go | 91 ++++++++ pkg/plugin/dropreason/ebpfsetup_linux.go | 197 ++++++++++++++++++ pkg/plugin/dropreason/types_linux.go | 41 +++- 4 files changed, 328 insertions(+), 134 deletions(-) create mode 100644 pkg/plugin/dropreason/ebpfsetup_linux.go diff --git a/pkg/plugin/dropreason/dropreason_linux.go b/pkg/plugin/dropreason/dropreason_linux.go index cfbee0886b..c22dc11770 100644 --- a/pkg/plugin/dropreason/dropreason_linux.go +++ b/pkg/plugin/dropreason/dropreason_linux.go @@ -13,13 +13,9 @@ import ( "runtime" "time" - "github.com/blang/semver/v4" "github.com/cilium/cilium/api/v1/flow" hubblev1 "github.com/cilium/cilium/pkg/hubble/api/v1" - "github.com/cilium/cilium/pkg/version" - "github.com/cilium/cilium/pkg/versioncheck" "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/perf" "github.com/microsoft/retina/internal/ktime" kcfg "github.com/microsoft/retina/pkg/config" @@ -131,7 +127,6 @@ func (dr *dropReason) Compile(ctx context.Context) error { } func (dr *dropReason) Init() error { - var err error // Get the absolute path to this file during runtime. dir, err := absPath() if err != nil { @@ -139,21 +134,12 @@ func (dr *dropReason) Init() error { } bpfOutputFile := fmt.Sprintf("%s/%s", dir, bpfObjectFileName) - - var objs interface{} - maps := &kprobeMaps{} - isMariner := plugincommon.IsAzureLinux() - - if !isMariner { - objs = &kprobeObjects{} //nolint:typecheck // this is a generated struct - maps = &objs.(*kprobeObjects).kprobeMaps - } else { - objs = &kprobeObjectsMariner{} //nolint:typecheck // needs to match a generated struct until we fix Mariner - maps = &objs.(*kprobeObjectsMariner).kprobeMaps - dr.l.Info("Detected Mariner distro") + spec, err := ebpf.LoadCollectionSpec(bpfOutputFile) + if err != nil { + return err //nolint:wrapcheck // no additional context needed } - spec, err := ebpf.LoadCollectionSpec(bpfOutputFile) + objs, maps, supportsFexit, err := dr.getEbpfPayload() if err != nil { return err } @@ -181,28 +167,10 @@ func (dr *dropReason) Init() error { progsKprobe, progsKprobeRet := buildKprobePrograms(objs) progsFexit := buildFexitPrograms(objs) - if dr.cfg.EnablePodLevel { - err = dr.attachKprobes(progsKprobe, progsKprobeRet) + if supportsFexit { + err = dr.attachFexitPrograms(progsFexit) } else { - var kv semver.Version - kv, err = version.GetKernelVersion() - if err != nil { - dr.l.Warn("Failed to get kernel version", zap.Error(err)) - - kv, err = plugincommon.GetKernelVersionMajMin() - if err != nil { - return fmt.Errorf("Failed to get kernel version: %w", err) //nolint:goerr113 //wrapping error from external module - } - } - dr.l.Info("Detected kernel >= ", zap.String("version", kv.String())) - - minVersionAmd64, _ := versioncheck.Version("5.5") - minVersionArm64, _ := versioncheck.Version("6.0") - if (runtime.GOARCH == "amd64" && kv.GTE(minVersionAmd64)) || runtime.GOARCH == "arm64" && kv.GTE(minVersionArm64) { - err = dr.attachFexitPrograms(progsFexit) - } else { - err = dr.attachKprobes(progsKprobe, progsKprobeRet) - } + err = dr.attachKprobes(progsKprobe, progsKprobeRet) } dr.metricsMapData = maps.RetinaDropreasonMetrics @@ -427,44 +395,6 @@ func (dr *dropReason) processMapValue(dataKey dropMetricKey, dataValue dropMetri dr.dropMetricAdd(dataKey.getType(), dataKey.getDirection(), pktCount, pktBytes) } -func (dr *dropReason) attachKprobes(kprobes, kprobesRet map[string]*ebpf.Program) error { - for name := range kprobes { - progLink, err := link.Kprobe(name, kprobes[name], nil) - if err != nil { - dr.l.Error("Failed to attach kprobe", zap.String("program", name), zap.Error(err)) - return fmt.Errorf("Failed to attach program: %w", err) //nolint:goerr113 //wrapping error from external module - } - dr.hooks = append(dr.hooks, progLink) - dr.l.Info("Attached kprobe", zap.String("program", name)) - } - - for name := range kprobesRet { - progLink, err := link.Kretprobe(name, kprobesRet[name], nil) - if err != nil { - dr.l.Error("Failed to attach kretprobe", zap.String("program", name), zap.Error(err)) - return fmt.Errorf("Failed to attach program: %w", err) //nolint:goerr113 //wrapping error from external module - } - dr.hooks = append(dr.hooks, progLink) - dr.l.Info("Attached kretprobe", zap.String("program", name)) - } - - return nil -} - -func (dr *dropReason) attachFexitPrograms(objs map[string]*ebpf.Program) error { - for name, prog := range objs { - progLink, err := link.AttachTracing(link.TracingOptions{Program: prog, AttachType: ebpf.AttachTraceFExit}) - if err != nil { - dr.l.Error("Failed to attach", zap.String("program", name), zap.Error(err)) - return fmt.Errorf("Failed to attach program: %w", err) //nolint:goerr113 //wrapping error from external module - } - dr.hooks = append(dr.hooks, progLink) - dr.l.Info("Attached program", zap.String("program", name)) - } - - return nil -} - func (dr *dropReason) Stop() error { if !dr.isRunning { return nil @@ -516,52 +446,3 @@ func absPath() (string, error) { dir := path.Dir(filename) return dir, nil } - -func buildKprobePrograms(objs any) (progsKprobe, progsKprobeRet map[string]*ebpf.Program) { - progsKprobe = make(map[string]*ebpf.Program) - progsKprobeRet = make(map[string]*ebpf.Program) - - switch o := objs.(type) { - case *kprobeObjects: - progsKprobe[inetCskAcceptFn] = o.InetCskAccept - progsKprobe[nfHookSlowFn] = o.NfHookSlow - progsKprobe[nfNatInetFn] = o.NfNatInetFn - progsKprobe[nfConntrackConfirmFn] = o.NfConntrackConfirm - - progsKprobeRet[nfHookSlowFn] = o.NfHookSlowRet - progsKprobeRet[inetCskAcceptFn] = o.InetCskAcceptRet - progsKprobeRet[tcpConnectFn] = o.TcpV4ConnectRet - progsKprobeRet[nfNatInetFn] = o.NfNatInetFnRet - progsKprobeRet[nfConntrackConfirmFn] = o.NfConntrackConfirmRet - - case *kprobeObjectsMariner: - progsKprobe[inetCskAcceptFn] = o.InetCskAccept - progsKprobe[nfHookSlowFn] = o.NfHookSlow - - progsKprobeRet[nfHookSlowFn] = o.NfHookSlowRet - progsKprobeRet[inetCskAcceptFn] = o.InetCskAcceptRet - progsKprobeRet[tcpConnectFn] = o.TcpV4ConnectRet - - } - return progsKprobe, progsKprobeRet -} - -func buildFexitPrograms(objs any) map[string]*ebpf.Program { - progsFexit := make(map[string]*ebpf.Program) - - switch o := objs.(type) { - case *kprobeObjects: - progsFexit[inetCskAcceptFnFexit] = o.InetCskAcceptFexit - progsFexit[nfHookSlowFnFexit] = o.NfHookSlowFexit - progsFexit[tcpV4ConnectFexit] = o.TcpV4ConnectFexit - progsFexit[nfNatInetFnFexit] = o.NfNatInetFnFexit - progsFexit[nfConntrackConfirmFnFexit] = o.NfConntrackConfirmFexit - - case *kprobeObjectsMariner: - progsFexit[inetCskAcceptFnFexit] = o.InetCskAcceptFexit - progsFexit[nfHookSlowFnFexit] = o.NfHookSlowFexit - progsFexit[tcpV4ConnectFexit] = o.TcpV4ConnectFexit - - } - return progsFexit -} diff --git a/pkg/plugin/dropreason/dropreason_linux_test.go b/pkg/plugin/dropreason/dropreason_linux_test.go index e494a03f02..675b81f20f 100644 --- a/pkg/plugin/dropreason/dropreason_linux_test.go +++ b/pkg/plugin/dropreason/dropreason_linux_test.go @@ -9,11 +9,13 @@ import ( "fmt" "os" "path" + "reflect" "runtime" "testing" "time" "unsafe" + "github.com/blang/semver/v4" "github.com/cilium/ebpf/perf" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/enricher" @@ -467,6 +469,95 @@ func TestDropReasonGenerate(t *testing.T) { } } +func mustVersion(v string) semver.Version { + ver, err := semver.Parse(v) + if err != nil { + panic(err) + } + return ver +} + +func TestResolveEbpfPayload(t *testing.T) { + tests := []struct { + name string + arch string + kv semver.Version + isMariner bool + isPodLevel bool + wantType string + wantSupportsFexit bool + }{ + { + name: "old kernel - fallback to allKprobeObjects", + arch: "amd64", + kv: mustVersion("5.4.0"), + isMariner: false, + isPodLevel: false, + wantType: "*dropreason.allKprobeObjects", + wantSupportsFexit: false, + }, + { + name: "new kernel - fexitObjects for Ubuntu", + arch: "amd64", + kv: mustVersion("5.10.0"), + isMariner: false, + isPodLevel: false, + wantType: "*dropreason.allFexitObjects", + wantSupportsFexit: true, + }, + { + name: "new kernel - marinerObjects for Mariner", + arch: "amd64", + kv: mustVersion("5.10.0"), + isMariner: true, + isPodLevel: false, + wantType: "*dropreason.marinerObjects", + wantSupportsFexit: true, + }, + { + name: "arm64 old kernel - fallback to allKprobeObjects", + arch: "arm64", + kv: mustVersion("5.8.0"), + isMariner: true, + isPodLevel: false, + wantType: "*dropreason.allKprobeObjects", + wantSupportsFexit: false, + }, + { + name: "arm64 new kernel - marinerObjects", + arch: "arm64", + kv: mustVersion("6.1.0"), + isMariner: true, + isPodLevel: false, + wantType: "*dropreason.marinerObjects", + wantSupportsFexit: true, + }, + { + name: "pod level - use allKprobeObjects", + arch: "amd64", + kv: mustVersion("5.15.0"), + isMariner: false, + isPodLevel: true, + wantType: "*dropreason.allKprobeObjects", + wantSupportsFexit: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + objs, _, isFexit := resolvePayload(tt.arch, tt.kv, tt.isMariner, tt.isPodLevel) + + if isFexit != tt.wantSupportsFexit { + t.Errorf("isFexit = %v, want %v", isFexit, tt.wantSupportsFexit) + } + + if gotType := reflect.TypeOf(objs).String(); gotType != tt.wantType { + t.Errorf("object type = %v, want %v", gotType, tt.wantType) + } + }) + } +} + // Helpers. func takeBackup() { // Get the directory of the current test file. diff --git a/pkg/plugin/dropreason/ebpfsetup_linux.go b/pkg/plugin/dropreason/ebpfsetup_linux.go new file mode 100644 index 0000000000..c0c0a6785d --- /dev/null +++ b/pkg/plugin/dropreason/ebpfsetup_linux.go @@ -0,0 +1,197 @@ +package dropreason + +import ( + "fmt" + "runtime" + + "github.com/blang/semver/v4" + "github.com/cilium/cilium/pkg/version" + "github.com/cilium/cilium/pkg/versioncheck" + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/link" + plugincommon "github.com/microsoft/retina/pkg/plugin/common" + "github.com/pkg/errors" + "go.uber.org/zap" +) + +const ( + MinAmdVersionNum = "5.5" + MinArmVersionNum = "6.0" +) + +/* +getEbpfPayload() returns the ebpf program and map objects to load, based on the kernel version, architecture, and distro. +We use fexit programs for better performance, and fall back to kprobes. + +eBPF Program Support Matrix +=========================== + +Program Type Selection: +- If: + - Arch == amd64 and kernel >= 5.5 + - Arch == arm64 and kernel >= 6.0 + → Use `fexit` + - Else: + → Use `kprobe` + +Scope Selection: +- If: + - Distro == Mariner + → Scope = core (only core kernel funcs) + - Else: + → Scope = all (core + module funcs) + ++-----------+------------------------+--------------+--------+ +| Distro | Arch + Kernel | Prog | Scope | ++-----------+------------------------+--------------+--------+ +| Mariner | amd64, kernel >= 5.5 | fexit | core | +| Mariner | arm64, kernel >= 6.0 | fexit | core | +| Non-Marin | amd64, kernel >= 5.5 | fexit | all | +| Non-Marin | arm64, kernel >= 6.0 | fexit | all | +| * | (otherwise) | kprobe | per OS | ++-----------+------------------------+--------------+--------+ + +core kernel funcs: +- tcp_v4_connect +- inet_csk_accept +- nf_hook_slow + +module funcs: +- nf_conntrack_confirm +- nf_nat_inet_fn +*/ + +func (dr *dropReason) getEbpfPayload() (objs interface{}, maps *kprobeMaps, supportsFexit bool, err error) { + isMariner := plugincommon.IsAzureLinux() + dr.l.Info("Distro check:", zap.Bool("isMariner", isMariner)) + + kv, err := version.GetKernelVersion() + if err != nil { + kv, err = plugincommon.GetKernelVersionMajMin() + if err != nil { + return nil, nil, false, fmt.Errorf("failed to get kernel version: %w", err) //nolint:goerr113 //wrapping error from external module + } + } + dr.l.Info("Detected kernel", zap.String("version", kv.String())) + + objs, maps, supportsFexit = resolvePayload(runtime.GOARCH, kv, isMariner, dr.cfg.EnablePodLevel) + return objs, maps, supportsFexit, nil +} + +func resolvePayload(arch string, kv semver.Version, isMariner, isPodLevel bool) (interface{}, *kprobeMaps, bool) { + minVersionAmd64, _ := versioncheck.Version(MinAmdVersionNum) + minVersionArm64, _ := versioncheck.Version(MinArmVersionNum) + + supportsFexit := (arch == "amd64" && kv.GTE(minVersionAmd64)) || + (arch == "arm64" && kv.GTE(minVersionArm64)) + + var objs interface{} + var maps *kprobeMaps + + switch { + case isPodLevel: // TODO: fexit support is being rolled out in two stages, remove this when we have it for advanced metrics. + objs = &allKprobeObjects{} //nolint:typecheck // this is a generated struct + maps = &objs.(*allKprobeObjects).kprobeMaps + case isMariner && supportsFexit: // Mariner supports a subset of the fexit programs, need to check for it first. + objs = &marinerObjects{} //nolint:typecheck // needs to match a generated struct until we fix Mariner + maps = &objs.(*marinerObjects).kprobeMaps + case supportsFexit: + objs = &allFexitObjects{} //nolint:typecheck // this is a generated struct + maps = &objs.(*allFexitObjects).kprobeMaps + default: + objs = &allKprobeObjects{} //nolint:typecheck // this is a generated struct + maps = &objs.(*allKprobeObjects).kprobeMaps + } + + return objs, maps, (supportsFexit && !isPodLevel) +} + +func (dr *dropReason) attachKprobes(kprobes, kprobesRet map[string]*ebpf.Program) error { + for name := range kprobes { + progLink, err := link.Kprobe(name, kprobes[name], nil) + if err != nil { + dr.l.Error("Failed to attach kprobe", zap.String("program", name), zap.Error(err)) + } else { + dr.hooks = append(dr.hooks, progLink) + dr.l.Info("Attached kprobe", zap.String("program", name)) + } + } + + // The kretprobes set metric values. If none were attached, report an error. + retprobeCount := 0 + for name := range kprobesRet { + progLink, err := link.Kretprobe(name, kprobesRet[name], nil) + if err != nil { + dr.l.Error("Failed to attach kretprobe", zap.String("program", name), zap.Error(err)) + } else { + dr.hooks = append(dr.hooks, progLink) + retprobeCount++ + dr.l.Info("Attached kretprobe", zap.String("program", name)) + } + } + if retprobeCount == 0 { + dr.l.Error("No kretprobes attached, cannot collect drop metrics") + return errors.New("No kretprobes attached, cannot collect drop metrics") //nolint:goerr113 // no sentinel type used + } + + return nil +} + +func (dr *dropReason) attachFexitPrograms(objs map[string]*ebpf.Program) error { + progCount := 0 + for name, prog := range objs { + progLink, err := link.AttachTracing(link.TracingOptions{Program: prog, AttachType: ebpf.AttachTraceFExit}) + if err != nil { + dr.l.Error("Failed to attach", zap.String("program", name), zap.Error(err)) + } else { + dr.hooks = append(dr.hooks, progLink) + progCount++ + dr.l.Info("Attached program", zap.String("program", name)) + } + } + + if progCount == 0 { + dr.l.Error("No programs attached, cannot collect drop metrics") + return errors.New("No programs attached, cannot collect drop metrics") //nolint:goerr113 // no sentinel type used + } + + return nil +} + +func buildKprobePrograms(objs any) (progsKprobe, progsKprobeRet map[string]*ebpf.Program) { + progsKprobe = make(map[string]*ebpf.Program) + progsKprobeRet = make(map[string]*ebpf.Program) + + if o, ok := objs.(*allKprobeObjects); ok { + progsKprobe[inetCskAcceptFn] = o.InetCskAccept + progsKprobe[nfHookSlowFn] = o.NfHookSlow + progsKprobe[nfNatInetFn] = o.NfNatInetFn + progsKprobe[nfConntrackConfirmFn] = o.NfConntrackConfirm + + progsKprobeRet[nfHookSlowFn] = o.NfHookSlowRet + progsKprobeRet[inetCskAcceptFn] = o.InetCskAcceptRet + progsKprobeRet[tcpConnectFn] = o.TcpV4ConnectRet + progsKprobeRet[nfNatInetFn] = o.NfNatInetFnRet + progsKprobeRet[nfConntrackConfirmFn] = o.NfConntrackConfirmRet + } + return progsKprobe, progsKprobeRet +} + +func buildFexitPrograms(objs any) map[string]*ebpf.Program { + progsFexit := make(map[string]*ebpf.Program) + + switch o := objs.(type) { + case *allFexitObjects: + progsFexit[inetCskAcceptFnFexit] = o.InetCskAcceptFexit + progsFexit[nfHookSlowFnFexit] = o.NfHookSlowFexit + progsFexit[tcpV4ConnectFexit] = o.TcpV4ConnectFexit + progsFexit[nfNatInetFnFexit] = o.NfNatInetFnFexit + progsFexit[nfConntrackConfirmFnFexit] = o.NfConntrackConfirmFexit + + case *marinerObjects: + progsFexit[inetCskAcceptFnFexit] = o.InetCskAcceptFexit + progsFexit[nfHookSlowFnFexit] = o.NfHookSlowFexit + progsFexit[tcpV4ConnectFexit] = o.TcpV4ConnectFexit + } + return progsFexit +} diff --git a/pkg/plugin/dropreason/types_linux.go b/pkg/plugin/dropreason/types_linux.go index a78fea8f85..5db5c363e2 100644 --- a/pkg/plugin/dropreason/types_linux.go +++ b/pkg/plugin/dropreason/types_linux.go @@ -42,22 +42,47 @@ type dropReason struct { externalChannel chan *hubblev1.Event } -type kprobeObjectsMariner struct { - kprobeProgramsMariner +type allFexitObjects struct { + allFexitPrograms kprobeMaps } -type kprobeProgramsMariner struct { - InetCskAccept *ebpf.Program `ebpf:"inet_csk_accept"` - InetCskAcceptRet *ebpf.Program `ebpf:"inet_csk_accept_ret"` +type allFexitPrograms struct { + InetCskAcceptFexit *ebpf.Program `ebpf:"inet_csk_accept_fexit"` + NfConntrackConfirmFexit *ebpf.Program `ebpf:"nf_conntrack_confirm_fexit"` + NfHookSlowFexit *ebpf.Program `ebpf:"nf_hook_slow_fexit"` + NfNatInetFnFexit *ebpf.Program `ebpf:"nf_nat_inet_fn_fexit"` + TcpV4ConnectFexit *ebpf.Program `ebpf:"tcp_v4_connect_fexit"` // nolint:revive // needs to match generated code +} + +type marinerObjects struct { + marinerPrograms + kprobeMaps +} + +type marinerPrograms struct { InetCskAcceptFexit *ebpf.Program `ebpf:"inet_csk_accept_fexit"` - NfHookSlow *ebpf.Program `ebpf:"nf_hook_slow"` - NfHookSlowRet *ebpf.Program `ebpf:"nf_hook_slow_ret"` NfHookSlowFexit *ebpf.Program `ebpf:"nf_hook_slow_fexit"` - TcpV4ConnectRet *ebpf.Program `ebpf:"tcp_v4_connect_ret"` // nolint:revive // needs to match generated code TcpV4ConnectFexit *ebpf.Program `ebpf:"tcp_v4_connect_fexit"` // nolint:revive // needs to match generated code } +type allKprobeObjects struct { + allKprobePrograms + kprobeMaps +} + +type allKprobePrograms struct { + InetCskAccept *ebpf.Program `ebpf:"inet_csk_accept"` + InetCskAcceptRet *ebpf.Program `ebpf:"inet_csk_accept_ret"` + NfConntrackConfirm *ebpf.Program `ebpf:"nf_conntrack_confirm"` + NfConntrackConfirmRet *ebpf.Program `ebpf:"nf_conntrack_confirm_ret"` + NfHookSlow *ebpf.Program `ebpf:"nf_hook_slow"` + NfHookSlowRet *ebpf.Program `ebpf:"nf_hook_slow_ret"` + NfNatInetFn *ebpf.Program `ebpf:"nf_nat_inet_fn"` + NfNatInetFnRet *ebpf.Program `ebpf:"nf_nat_inet_fn_ret"` + TcpV4ConnectRet *ebpf.Program `ebpf:"tcp_v4_connect_ret"` // nolint:revive // needs to match generated code +} + type ( returnValue uint32 ) From 1e26c4d3ab0743dd5df916b136f41978a7855476 Mon Sep 17 00:00:00 2001 From: Amilcar Aponte Date: Fri, 16 May 2025 22:15:02 +0100 Subject: [PATCH 018/448] fix(image): Adding ARM64 Operator image release (#1610) # Description This PR is a follow up from: https://github.com/microsoft/retina/pull/1538/files#diff-fb3f33cdd2a5865385222d244e9bdc9a7ebee2756d506f6495f83a5cff42b25a The ARM64 Operator image was added to the test workflow, and the ADO (Microsoft internal release) pipeline, but not to GHCR release flow. This PR fixes that. ## Related Issue https://github.com/microsoft/retina/issues/1582 ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed This flow was tested here: https://github.com/microsoft/retina/actions/runs/15065640778/job/42350022052 ![image](https://github.com/user-attachments/assets/6d74dbb0-4455-45e1-96cf-a890d9e88b78) ![image](https://github.com/user-attachments/assets/4c51ab47-2ba9-477a-910c-b2a1b0b9f849) ![image](https://github.com/user-attachments/assets/9b2da4bc-3208-4fb2-8063-430039cfff27) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/workflows/release-images.yaml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 3a3bd417d0..8722f4ef5d 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -112,7 +112,7 @@ jobs: strategy: matrix: platform: ["linux"] - arch: ["amd64"] + arch: ["amd64", "arm64"] steps: - name: Checkout code diff --git a/Makefile b/Makefile index 2f8d6b28cb..80ccaf3b37 100644 --- a/Makefile +++ b/Makefile @@ -349,7 +349,7 @@ manifest-retina-image: ## create a multiplatform manifest for the retina image manifest-operator-image: ## create a multiplatform manifest for the operator image $(eval FULL_IMAGE_NAME=$(IMAGE_REGISTRY)/$(RETINA_OPERATOR_IMAGE):$(TAG)) - docker buildx imagetools create -t $(FULL_IMAGE_NAME) $(foreach platform,linux/amd64, $(FULL_IMAGE_NAME)-$(subst /,-,$(platform))) + docker buildx imagetools create -t $(FULL_IMAGE_NAME) $(foreach platform,linux/amd64 linux/arm64, $(FULL_IMAGE_NAME)-$(subst /,-,$(platform))) manifest-shell-image: $(eval FULL_IMAGE_NAME=$(IMAGE_REGISTRY)/$(RETINA_SHELL_IMAGE):$(TAG)) From 31cdf422a5ffe521c3bb6a8c532e1c62497f5713 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Mon, 19 May 2025 18:04:18 +0200 Subject: [PATCH 019/448] fix(conntrack): improve traffic direction detection (#1562) # Description Use only the initial SYN packet to determine the connection direction and not also the SYN-ACK. This should only happen in very unfortunate cases (when the agent is injected in the middle of a TCP handshake). Just a couple of additional questions: * Since we don't know the direction, shouldn't this https://github.com/microsoft/retina/blob/7287769254ac5b1597bd617bfb206e8c7047fe3f/pkg/plugin/conntrack/_cprog/conntrack.c#L220 be `TRAFFIC_DIRECTION_UNKNOWN`? * Is there any particular heuristic behind this ACK detection? https://github.com/microsoft/retina/blob/7287769254ac5b1597bd617bfb206e8c7047fe3f/pkg/plugin/conntrack/_cprog/conntrack.c#L224 Almost all TCP packets should have the ACK flag, so it seems a 50% possibility to get the right direction ## Related Issue no ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Andrea Terzolo --- pkg/plugin/conntrack/_cprog/conntrack.c | 33 ++++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c index a86cf49bab..73761865c9 100644 --- a/pkg/plugin/conntrack/_cprog/conntrack.c +++ b/pkg/plugin/conntrack/_cprog/conntrack.c @@ -130,8 +130,9 @@ static __always_inline __u8 _ct_get_traffic_direction(__u8 observation_point) { * @arg *p pointer to the packet to be processed. * @arg key The key to be used to create the new connection. * @arg observation_point The point in the network stack where the packet is observed. + * @arg is_reply true if the packet is a SYN-ACK packet. False if it is a SYN packet. */ -static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key key, __u8 observation_point) { +static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key key, __u8 observation_point, bool is_reply) { struct ct_entry new_value; __builtin_memset(&new_value, 0, sizeof(struct ct_entry)); __u64 now = bpf_mono_now(); @@ -140,19 +141,30 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru return false; } new_value.eviction_time = now + CT_SYN_TIMEOUT; - new_value.flags_seen_tx_dir = p->flags; + if(is_reply) { + new_value.flags_seen_rx_dir = p->flags; + new_value.last_report_rx_dir = now; + } else { + new_value.flags_seen_tx_dir = p->flags; + new_value.last_report_tx_dir = now; + } new_value.is_direction_unknown = false; new_value.traffic_direction = _ct_get_traffic_direction(observation_point); #ifdef ENABLE_CONNTRACK_METRICS - new_value.conntrack_metadata.packets_tx_count = 1; - new_value.conntrack_metadata.bytes_tx_count = p->bytes; + if(is_reply){ + new_value.conntrack_metadata.packets_rx_count = 1; + new_value.conntrack_metadata.bytes_rx_count = p->bytes; + } else { + new_value.conntrack_metadata.packets_tx_count = 1; + new_value.conntrack_metadata.bytes_tx_count = p->bytes; + } // Update initial conntrack metadata for the connection. __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS // Update packet - p->is_reply = false; + p->is_reply = is_reply; p->traffic_direction = new_value.traffic_direction; bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY); return true; @@ -198,10 +210,13 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c * @arg observation_point The point in the network stack where the packet is observed. */ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct ct_v4_key key, struct ct_v4_key reverse_key, __u8 observation_point) { - // Check if the packet is a SYN packet. - if (p->flags & TCP_SYN) { - // Create a new connection with a timeout of CT_SYN_TIMEOUT. - return _ct_create_new_tcp_connection(p, key, observation_point); + u8 tcp_handshake = p->flags & (TCP_SYN|TCP_ACK); + if (tcp_handshake == TCP_SYN) { + // We have a SYN, we set `is_reply` to false and we provide `key` + return _ct_create_new_tcp_connection(p, key, observation_point, false); + } else if(tcp_handshake == TCP_SYN|TCP_ACK) { + // We have a SYN-ACK, we set `is_reply` to true and we provide `reverse_key` + return _ct_create_new_tcp_connection(p, reverse_key, observation_point, true); } // The packet is not a SYN packet and the connection corresponding to this packet is not found. From 664f12f7c7ffcf0efe2aceb0324bcf98c0260287 Mon Sep 17 00:00:00 2001 From: Igor Klemenski Date: Mon, 19 May 2025 10:22:42 -0700 Subject: [PATCH 020/448] fix: e2e job skipped due to yaml syntax error (#1614) Our E2e job is getting skipped in the merge queue, because of YAML parsing errors. We have invalid syntax in the if-statements checking for success of prerequisite jobs that need to run for `manifests` and `E2E` to run. Looks like this used to be ignored and those jobs just ran, while recently Github started enforcing stricter YAML syntax validation which is causing these jobs to get skipped! It started about a week ago, example errors at the bottom of the page: https://github.com/microsoft/retina/actions/runs/14842770818 ![image](https://github.com/user-attachments/assets/1906d486-e581-4ed3-8c93-baa8b3f15e0d) --- .github/workflows/images.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index dbf20a09f2..18dfc3e7c2 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -264,8 +264,8 @@ jobs: IS_MERGE_GROUP: ${{ github.event_name == 'merge_group' }} manifests: - if: ${{ github.event_name == 'merge_group' && success('retina-images') && success('retina-win-images') && success('operator-images') && success('retina-shell-images')}} name: Generate Manifests + if: ${{ github.event_name == 'merge_group' }} runs-on: ubuntu-latest needs: [ @@ -303,10 +303,10 @@ jobs: IMAGE_REGISTRY=${{ vars.ACR_NAME }} \ e2e: - if: ${{ github.event_name == 'merge_group' && success('manifests')}} name: Run E2E Tests - runs-on: ubuntu-latest + if: ${{ github.event_name == 'merge_group' }} needs: [manifests] + runs-on: ubuntu-latest steps: - name: Checkout code @@ -336,7 +336,7 @@ jobs: go test -v ./test/e2e/. -timeout 60m -tags=e2e -count=1 -args -image-tag=$(make version) -image-registry=${{ vars.ACR_NAME }} -image-namespace=${{ github.repository}} perf-test-basic: - if: ${{ github.event_name == 'merge_group' && success('manifests')}} + if: ${{ github.event_name == 'merge_group'}} needs: [manifests] uses: ./.github/workflows/perf-template.yaml with: @@ -352,7 +352,7 @@ jobs: azure-app-insights-key: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} perf-test-advanced: - if: ${{ github.event_name == 'merge_group' && success('manifests')}} + if: ${{ github.event_name == 'merge_group'}} needs: [manifests] uses: ./.github/workflows/perf-template.yaml with: From 37d15667662c0dc47f0c21d9269444233e5e56e9 Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Tue, 20 May 2025 14:06:57 -0700 Subject: [PATCH 021/448] fix: Allow RBAC for endpoints to the standard chart (#1619) # Description Adds RBAC to allow querying `endpoints` in the standard chart. Fixes errors introduced by https://github.com/microsoft/retina/pull/1573 for failures to query for `endpoints` when the legacy control plane is deployed. ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Deployed with new version of the chart, no longer receive errors like ``` retina ts=2025-05-20T20:23:52.758Z level=error caller=apiserver/apiserver.go:120 msg="failed to initialize new cache" error="failed to retrieve ips from kubernetes endpoint: retrieving kubernetes endpoint: endpoints \"kubernetes\" is forbidden retina ts=2025-05-20T20:23:52.758Z level=error caller=watchermanager/watchermanager.go:76 msg="refresh failed" error="failed to retrieve ips from kubernetes endpoint: retrieving kubernetes endpoint: endpoints \"kubernetes\" is forbidden ``` --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- .../manifests/controller/helm/retina/templates/rbac.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml b/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml index 193055cb9d..2f0046bf11 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml @@ -9,7 +9,7 @@ metadata: name: retina-cluster-reader rules: - apiGroups: [""] # "" indicates the core API group - resources: ["pods", "services", "replicationcontrollers", "nodes", "namespaces"] + resources: ["endpoints", "pods", "services", "replicationcontrollers", "nodes", "namespaces"] verbs: ["get", "watch", "list"] - apiGroups: ["apps"] resources: ["deployments", "replicasets"] @@ -30,6 +30,7 @@ rules: - "" resources: - namespaces + - endpoints verbs: - get - list From 74ab511c1632824ff09aabfbc7b1a0f87401a4b9 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Wed, 28 May 2025 11:50:18 +0100 Subject: [PATCH 022/448] chore(ciliumeventobserver): Remove warn for messageType not supported (#1629) # Description This warning is being logged to many times. ![image](https://github.com/user-attachments/assets/2e52935d-e3af-44d8-b88c-243f9749b425) ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/plugin/ciliumeventobserver/parser_linux.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/plugin/ciliumeventobserver/parser_linux.go b/pkg/plugin/ciliumeventobserver/parser_linux.go index 78e6a772b9..e653c99c6f 100644 --- a/pkg/plugin/ciliumeventobserver/parser_linux.go +++ b/pkg/plugin/ciliumeventobserver/parser_linux.go @@ -17,8 +17,7 @@ import ( ) var ( - ErrNotImplemented = errors.New("Error, not implemented") - ErrEmptyData = errors.New("empty data") + ErrEmptyData = errors.New("empty data") ) func (p *parser) Init() error { @@ -75,7 +74,7 @@ func (p *parser) Decode(pl *payload.Payload) (*v1.Event, error) { // Log Records can be DNS traces for CNP related pods // AccessLogs can also reflect kafka related metrics monEvent.Payload = &observerTypes.AgentEvent{} - return nil, ErrNotImplemented //nolint:goerr113 //no specific handling expected + return nil, nil //nolint:goerr113 //no specific handling expected // MessageTypeTraceSock and MessageTypeDebug are also perf events but have their own dedicated decoders in cilium. case monitorAPI.MessageTypeDrop, monitorAPI.MessageTypeTrace, monitorAPI.MessageTypePolicyVerdict, monitorAPI.MessageTypeCapture: perfEvent := &observerTypes.PerfEvent{} From 7e470501c0f8aef8edb6258538a61e739efe03bb Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 28 May 2025 19:31:32 +0100 Subject: [PATCH 023/448] docs: update control-plane and data-plane images (#1631) # Description Documentation update: Update control-plane and data-plane images in architecture page ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- .../img/control-plane.excalidraw | 545 ++++++++++++++---- docs/01-Introduction/img/control-plane.png | Bin 284963 -> 90653 bytes .../01-Introduction/img/data-plane.excalidraw | 190 +++--- docs/01-Introduction/img/data-plane.png | Bin 168958 -> 144476 bytes 4 files changed, 532 insertions(+), 203 deletions(-) diff --git a/docs/01-Introduction/img/control-plane.excalidraw b/docs/01-Introduction/img/control-plane.excalidraw index 997b287f7d..f8e02f8c43 100644 --- a/docs/01-Introduction/img/control-plane.excalidraw +++ b/docs/01-Introduction/img/control-plane.excalidraw @@ -5,8 +5,8 @@ "elements": [ { "type": "rectangle", - "version": 230, - "versionNonce": 171869816, + "version": 370, + "versionNonce": 591263446, "index": "at", "isDeleted": false, "id": "e3X3FsYsKyc5vzIaQEkdw", @@ -17,11 +17,11 @@ "opacity": 100, "angle": 0, "x": 78.5, - "y": 841.2285322675798, + "y": 795.2285322675798, "strokeColor": "#2f9e44", "backgroundColor": "transparent", "width": 593, - "height": 320.77146773242015, + "height": 366.77146773242015, "seed": 1251338007, "groupIds": [], "frameId": null, @@ -29,14 +29,14 @@ "type": 3 }, "boundElements": [], - "updated": 1736986598046, + "updated": 1748440447638, "link": null, "locked": false }, { "type": "rectangle", - "version": 204, - "versionNonce": 1938447224, + "version": 508, + "versionNonce": 1311912598, "index": "ay", "isDeleted": false, "id": "s76sKmY7lWfW7aIIgFJbD", @@ -46,12 +46,12 @@ "roughness": 0, "opacity": 100, "angle": 0, - "x": 264.68867302857984, - "y": 1013.5, + "x": 149.0713857748221, + "y": 934.9329807812408, "strokeColor": "#1e1e1e", "backgroundColor": "#b2f2bb", - "width": 216, - "height": 99, + "width": 172.61728725375775, + "height": 84.56701921875924, "seed": 747932279, "groupIds": [], "frameId": null, @@ -70,16 +70,20 @@ { "id": "DUD5pdi7NQXIRxtee70x9", "type": "arrow" + }, + { + "id": "6NVvUWMSCK2NWmpPxEvD1", + "type": "arrow" } ], - "updated": 1736986670614, + "updated": 1748440447638, "link": null, "locked": false }, { "type": "text", - "version": 405, - "versionNonce": 1946433912, + "version": 866, + "versionNonce": 1296346134, "index": "az", "isDeleted": false, "id": "xuSA2bAc_t-HYY8gtKTf6", @@ -89,18 +93,18 @@ "roughness": 1, "opacity": 100, "angle": 0, - "x": 333.01870537721265, - "y": 1050.5, + "x": 196.09006663314628, + "y": 964.7164903906204, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", - "width": 79.33993530273438, + "width": 78.57992553710938, "height": 25, "seed": 969847626, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], - "updated": 1736986649279, + "updated": 1748440447638, "link": null, "locked": false, "fontSize": 20, @@ -115,8 +119,8 @@ }, { "type": "rectangle", - "version": 577, - "versionNonce": 1974394232, + "version": 682, + "versionNonce": 727629846, "index": "b00", "isDeleted": false, "id": "ffioimfd5lplFqrar_3MY", @@ -138,18 +142,27 @@ "roundness": { "type": 3 }, - "boundElements": [], - "updated": 1736984179771, + "boundElements": [ + { + "id": "QuZ5FBcpl4jamVYT2fW3w", + "type": "arrow" + }, + { + "id": "CFgmxr_lGn-ZQtxsGWPsU", + "type": "arrow" + } + ], + "updated": 1748440447638, "link": null, "locked": false }, { "id": "QuZ5FBcpl4jamVYT2fW3w", "type": "arrow", - "x": 367.48664235385485, - "y": 1206.3092702754698, - "width": 0.23669352213681805, - "height": 90.54554607871114, + "x": 231.48664235385493, + "y": 1212.931885150108, + "width": 5.684341886080802e-14, + "height": 84.15842385058886, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -165,11 +178,11 @@ "type": 2 }, "seed": 2131312471, - "version": 152, - "versionNonce": 37238904, + "version": 780, + "versionNonce": 151194506, "isDeleted": false, "boundElements": [], - "updated": 1736986697521, + "updated": 1748440447640, "link": null, "locked": false, "points": [ @@ -178,17 +191,20 @@ 0 ], [ - 0.23669352213681805, - -90.54554607871114 + -5.684341886080802e-14, + -84.15842385058886 ] ], "lastCommittedPoint": null, - "startBinding": null, + "startBinding": { + "elementId": "ffioimfd5lplFqrar_3MY", + "focus": -0.4764258714124793, + "gap": 15.024103747967729 + }, "endBinding": { - "elementId": "s76sKmY7lWfW7aIIgFJbD", - "focus": 0.08569938797777649, - "gap": 3.2637241967586306, - "fixedPoint": null + "elementId": "mOQHb51yxdi4LJPn8XGhd", + "focus": 0.05509355735459114, + "gap": 9.71649039062072 }, "startArrowhead": null, "endArrowhead": "arrow", @@ -197,8 +213,8 @@ { "id": "CvGBI1ByJ4ksItctBUyD7", "type": "arrow", - "x": 367.2357749871671, - "y": 830.3497040580879, + "x": 362.2357749871671, + "y": 777.3497040580879, "width": 0.7384282555123036, "height": 85.65469253861232, "angle": 0, @@ -216,11 +232,11 @@ "type": 2 }, "seed": 2136439543, - "version": 593, - "versionNonce": 115321608, + "version": 736, + "versionNonce": 1326047574, "isDeleted": false, "boundElements": [], - "updated": 1736986697521, + "updated": 1748440453822, "link": null, "locked": false, "points": [ @@ -262,11 +278,11 @@ "type": 3 }, "seed": 1540148744, - "version": 1049, - "versionNonce": 901965576, + "version": 1136, + "versionNonce": 143466134, "isDeleted": false, "boundElements": [], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false }, @@ -292,11 +308,11 @@ "type": 3 }, "seed": 2081803528, - "version": 1051, - "versionNonce": 696839544, + "version": 1138, + "versionNonce": 1766473162, "isDeleted": false, "boundElements": [], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false }, @@ -322,8 +338,8 @@ "type": 3 }, "seed": 1223093256, - "version": 997, - "versionNonce": 1105249800, + "version": 1084, + "versionNonce": 1440275414, "isDeleted": false, "boundElements": [ { @@ -331,16 +347,16 @@ "id": "80Rqys5FW5W8TbyqTbjJL" } ], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false }, { "id": "80Rqys5FW5W8TbyqTbjJL", "type": "text", - "x": 179.63206172332542, + "x": 180.38213801727073, "y": 1301.8987447193506, - "width": 78.36387634277344, + "width": 76.86372375488281, "height": 28.786636059782506, "angle": 0, "strokeColor": "#1e1e1e", @@ -355,11 +371,11 @@ "index": "b14", "roundness": null, "seed": 1010576136, - "version": 1411, - "versionNonce": 1576828536, + "version": 1665, + "versionNonce": 898888842, "isDeleted": false, "boundElements": [], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false, "text": "Plugins", @@ -394,11 +410,11 @@ "type": 3 }, "seed": 814844424, - "version": 1343, - "versionNonce": 1827325192, + "version": 1430, + "versionNonce": 356184342, "isDeleted": false, "boundElements": [], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false }, @@ -424,11 +440,11 @@ "type": 3 }, "seed": 1357056264, - "version": 1342, - "versionNonce": 1070985080, + "version": 1429, + "versionNonce": 620286794, "isDeleted": false, "boundElements": [], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false }, @@ -454,8 +470,8 @@ "type": 3 }, "seed": 145532936, - "version": 1347, - "versionNonce": 1146938376, + "version": 1434, + "versionNonce": 1646812758, "isDeleted": false, "boundElements": [ { @@ -463,16 +479,16 @@ "id": "VmiWjaSbxHfEmmAKWJXGr" } ], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false }, { "id": "VmiWjaSbxHfEmmAKWJXGr", "type": "text", - "x": 440.54417270080165, + "x": 441.29424899474697, "y": 1297.6899726837808, - "width": 103.43266296386719, + "width": 101.93251037597656, "height": 28.786636059782506, "angle": 0, "strokeColor": "#1e1e1e", @@ -487,11 +503,11 @@ "index": "b18", "roundness": null, "seed": 1944741640, - "version": 1768, - "versionNonce": 1733902456, + "version": 2022, + "versionNonce": 2043927050, "isDeleted": false, "boundElements": [], - "updated": 1736984179772, + "updated": 1748440447638, "link": null, "locked": false, "text": "Watchers", @@ -507,8 +523,8 @@ { "id": "yQRBtn4Sn8fhshiuriGJP", "type": "image", - "x": 271.2705725972662, - "y": 649.7836515423428, + "x": 266.2705725972662, + "y": 596.7836515423428, "width": 91.30937122163323, "height": 90.83332061767578, "angle": 0, @@ -524,11 +540,11 @@ "index": "b19", "roundness": null, "seed": 162758776, - "version": 724, - "versionNonce": 225378168, + "version": 867, + "versionNonce": 1744832266, "isDeleted": false, "boundElements": [], - "updated": 1736986606306, + "updated": 1748440453822, "link": null, "locked": false, "status": "saved", @@ -549,8 +565,8 @@ { "id": "1KQ6WLF-oBYjWDBh9VwJZ", "type": "image", - "x": 369.2471191118682, - "y": 647.689869117416, + "x": 364.2471191118682, + "y": 594.689869117416, "width": 104.1665649414062, "height": 95.02088546752927, "angle": 0, @@ -566,11 +582,11 @@ "index": "b1A", "roundness": null, "seed": 1045750136, - "version": 515, - "versionNonce": 1062228088, + "version": 658, + "versionNonce": 489637526, "isDeleted": false, "boundElements": [], - "updated": 1736986606306, + "updated": 1748440453822, "link": null, "locked": false, "status": "saved", @@ -590,8 +606,8 @@ }, { "type": "rectangle", - "version": 269, - "versionNonce": 1322507640, + "version": 561, + "versionNonce": 836822218, "index": "b1F", "isDeleted": false, "id": "EK8sn12c99l9gSQpC7PqR", @@ -601,12 +617,12 @@ "roughness": 0, "opacity": 100, "angle": 0, - "x": 261.61523574512586, - "y": 872.4248518016716, + "x": 145.61523574512586, + "y": 827.4248518016716, "strokeColor": "#1e1e1e", "backgroundColor": "#b2f2bb", - "width": 216, - "height": 99, + "width": 172.61728725375775, + "height": 84.56701921875924, "seed": 459565832, "groupIds": [], "frameId": null, @@ -617,20 +633,16 @@ { "type": "text", "id": "QgoUyOB0rWShIdxYAZlB5" - }, - { - "id": "DUD5pdi7NQXIRxtee70x9", - "type": "arrow" } ], - "updated": 1736986670614, + "updated": 1748440460753, "link": null, "locked": false }, { "type": "text", - "version": 484, - "versionNonce": 1598835576, + "version": 933, + "versionNonce": 947412874, "index": "b1G", "isDeleted": false, "id": "QgoUyOB0rWShIdxYAZlB5", @@ -640,18 +652,18 @@ "roughness": 1, "opacity": 100, "angle": 0, - "x": 296.885285793954, - "y": 909.4248518016716, + "x": 159.32393430364536, + "y": 857.2083614110512, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", - "width": 145.45989990234375, + "width": 145.19989013671875, "height": 25, "seed": 11651592, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], - "updated": 1736986662222, + "updated": 1748440447638, "link": null, "locked": false, "fontSize": 20, @@ -665,12 +677,88 @@ "lineHeight": 1.25 }, { - "id": "DUD5pdi7NQXIRxtee70x9", + "type": "rectangle", + "version": 543, + "versionNonce": 238137354, + "index": "b1I", + "isDeleted": false, + "id": "mOQHb51yxdi4LJPn8XGhd", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 149.93304893483042, + "y": 1039.5795780498563, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 172.61728725375775, + "height": 84.56701921875924, + "seed": 485845386, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "h6vbXCI82MyW08QlpWzUS" + }, + { + "id": "QuZ5FBcpl4jamVYT2fW3w", + "type": "arrow" + } + ], + "updated": 1748440447638, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 909, + "versionNonce": 781419350, + "index": "b1J", + "isDeleted": false, + "id": "h6vbXCI82MyW08QlpWzUS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 180.0217447467679, + "y": 1069.363087659236, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 112.43989562988281, + "height": 25, + "seed": 1784916042, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1748440447638, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "Ring Buffer", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "mOQHb51yxdi4LJPn8XGhd", + "originalText": "Ring Buffer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "_e8OSfo2Im20ekq3_CqUK", "type": "arrow", - "x": 367.6049891149232, - "y": 1006.8617545663202, - "width": 0, - "height": 31.51517001065349, + "x": 231.28312952460504, + "y": 1039.2631403180974, + "width": 0.08287392579143216, + "height": 18.800105317722455, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -681,16 +769,16 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "b1H", + "index": "b1L", "roundness": { "type": 2 }, - "seed": 1829638408, - "version": 31, - "versionNonce": 411724152, + "seed": 1162155786, + "version": 762, + "versionNonce": 1490650378, "isDeleted": false, - "boundElements": null, - "updated": 1736986697521, + "boundElements": [], + "updated": 1748440447638, "link": null, "locked": false, "points": [ @@ -698,24 +786,248 @@ 0, 0 ], + [ + -0.08287392579143216, + -18.800105317722455 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "type": "rectangle", + "version": 695, + "versionNonce": 187722186, + "index": "b1M", + "isDeleted": false, + "id": "61pa7CE40d3XVWBJLJB5v", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 426.9330489348304, + "y": 935.5795780498568, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 172.61728725375775, + "height": 84.56701921875924, + "seed": 333335050, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "zMkhTJe9b_GQQ8HbTxa1-" + }, + { + "id": "CFgmxr_lGn-ZQtxsGWPsU", + "type": "arrow" + }, + { + "id": "6NVvUWMSCK2NWmpPxEvD1", + "type": "arrow" + } + ], + "updated": 1748440447638, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1056, + "versionNonce": 1513640906, + "index": "b1N", + "isDeleted": false, + "id": "zMkhTJe9b_GQQ8HbTxa1-", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 485.11171819647495, + "y": 965.3630876592364, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 56.25994873046875, + "height": 25, + "seed": 1113356490, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1748440447638, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "Cache", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "61pa7CE40d3XVWBJLJB5v", + "originalText": "Cache", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "CFgmxr_lGn-ZQtxsGWPsU", + "type": "arrow", + "x": 519.9420862849297, + "y": 1213.5586393663832, + "width": 0.4599132255937093, + "height": 184.56031911299942, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1O", + "roundness": { + "type": 2 + }, + "seed": 181407178, + "version": 949, + "versionNonce": 141363786, + "isDeleted": false, + "boundElements": [], + "updated": 1748440447640, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -0.4599132255937093, + -184.56031911299942 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ffioimfd5lplFqrar_3MY", + "focus": 0.4978491902677033, + "gap": 13.056926879035927 + }, + "endBinding": { + "elementId": "61pa7CE40d3XVWBJLJB5v", + "focus": -0.07073023493432183, + "gap": 17.716490390620038 + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "6NVvUWMSCK2NWmpPxEvD1", + "type": "arrow", + "x": 329.2274001542904, + "y": 978.2756347614246, + "width": 90.0471458881147, + "height": 0.5773793669147835, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1P", + "roundness": { + "type": 2 + }, + "seed": 1528929994, + "version": 411, + "versionNonce": 1873359114, + "isDeleted": false, + "boundElements": null, + "updated": 1748440447640, + "link": null, + "locked": false, + "points": [ [ 0, - -31.51517001065349 + 0 + ], + [ + 90.0471458881147, + -0.5773793669147835 ] ], "lastCommittedPoint": null, "startBinding": { "elementId": "s76sKmY7lWfW7aIIgFJbD", - "focus": -0.00487150396282619, - "gap": 6.638245433679799, - "fixedPoint": null + "focus": 0.03894183060552685, + "gap": 8.553019533129486 }, "endBinding": { - "elementId": "EK8sn12c99l9gSQpC7PqR", - "focus": -0.023586248661747734, - "gap": 3.9217327539951157, - "fixedPoint": null + "elementId": "61pa7CE40d3XVWBJLJB5v", + "focus": 0.017911219478604776, + "gap": 8.691356373121096 + }, + "startArrowhead": "arrow", + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "EloHGnpWQI88pjLDdZIaF", + "type": "arrow", + "x": 230.28312952460504, + "y": 933.2631403180972, + "width": 0.08287392579143216, + "height": 18.800105317722455, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1Q", + "roundness": { + "type": 2 }, + "seed": 729114454, + "version": 807, + "versionNonce": 1806840650, + "isDeleted": false, + "boundElements": [], + "updated": 1748440465451, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -0.08287392579143216, + -18.800105317722455 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, "startArrowhead": null, "endArrowhead": "arrow", "elbowed": false @@ -725,7 +1037,8 @@ "gridSize": 20, "gridStep": 5, "gridModeEnabled": false, - "viewBackgroundColor": "#ffffff" + "viewBackgroundColor": "#ffffff", + "lockedMultiSelections": {} }, "files": { "12236d9445da554c5fe0bbb860b540c2168c74a1": { diff --git a/docs/01-Introduction/img/control-plane.png b/docs/01-Introduction/img/control-plane.png index 91ebbb572aa43bd86d403236f9a5e5a6640979e6..3f23aa6d4cb47adaab35bbb2b161bec495788470 100644 GIT binary patch literal 90653 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 XSnK}8=Ck*e7=Xaj)z4*}Q$iB}tJb$7 literal 284963 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⋘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%0A=2A3Ya~6xv(-4Z~|k#!nf@;|)Ud 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

t&;8Y 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 diff --git a/docs/01-Introduction/img/data-plane.excalidraw b/docs/01-Introduction/img/data-plane.excalidraw index 73be74a76d..9df4faba21 100644 --- a/docs/01-Introduction/img/data-plane.excalidraw +++ b/docs/01-Introduction/img/data-plane.excalidraw @@ -588,7 +588,8 @@ "startBinding": null, "endBinding": null, "startArrowhead": null, - "endArrowhead": null + "endArrowhead": null, + "polygon": false }, { "id": "ydmFub-8BoqVbnYfipJ-t", @@ -1252,16 +1253,11 @@ "index": "b1X", "roundness": null, "seed": 2023979896, - "version": 897, - "versionNonce": 1068160264, + "version": 898, + "versionNonce": 1900992394, "isDeleted": false, - "boundElements": [ - { - "id": "1tRtua1u0RkMdUh3gjcmi", - "type": "arrow" - } - ], - "updated": 1736981707109, + "boundElements": [], + "updated": 1748438210474, "link": null, "locked": false, "text": "Watcher Manager", @@ -1274,61 +1270,6 @@ "autoResize": true, "lineHeight": 1.25 }, - { - "id": "1tRtua1u0RkMdUh3gjcmi", - "type": "arrow", - "x": 1176.7477959794871, - "y": 338.2328976508133, - "width": 85.04785606997076, - "height": 137.79711176768973, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "#96f2d7", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 0, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "b1Y", - "roundness": { - "type": 2 - }, - "seed": 1184189560, - "version": 738, - "versionNonce": 1868748296, - "isDeleted": false, - "boundElements": [], - "updated": 1736981707109, - "link": null, - "locked": false, - "points": [ - [ - 0, - 0 - ], - [ - -1.5482821546930372, - -63.47956834241896 - ], - [ - -85.04785606997076, - -137.79711176768973 - ] - ], - "lastCommittedPoint": null, - "startBinding": { - "elementId": "dpekxaD77Y_HDd20Rd59g", - "focus": 1.1146493866138798, - "gap": 11.602100636366941, - "fixedPoint": null - }, - "endBinding": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "elbowed": false - }, { "id": "SNQw7x8t7zQGeYtXwT3W1", "type": "rectangle", @@ -1381,8 +1322,8 @@ "type": 3 }, "seed": 1396873080, - "version": 169, - "versionNonce": 1662242168, + "version": 171, + "versionNonce": 325684630, "isDeleted": false, "boundElements": [ { @@ -1390,17 +1331,17 @@ "id": "_pl-vyPSCNw_D24KjRN3P" } ], - "updated": 1736981706947, + "updated": 1748437643530, "link": null, "locked": false }, { "id": "_pl-vyPSCNw_D24KjRN3P", "type": "text", - "x": 869.3600695168553, - "y": 129.82987544409286, - "width": 71.62249755859375, - "height": 22.613951497751323, + "x": 848.9513704812108, + "y": 128.63685119296852, + "width": 112.43989562988281, + "height": 25, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "#b2f2bb", @@ -1414,20 +1355,20 @@ "index": "b1bG", "roundness": null, "seed": 489024376, - "version": 236, - "versionNonce": 2083049336, + "version": 252, + "versionNonce": 1209273674, "isDeleted": false, "boundElements": [], - "updated": 1736981706947, + "updated": 1748438385414, "link": null, "locked": false, - "text": "Enricher", - "fontSize": 18.091161198201057, + "text": "Ring Buffer", + "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", "containerId": "z9YoMOkSFkPWTsUTTSkwH", - "originalText": "Enricher", + "originalText": "Ring Buffer", "autoResize": true, "lineHeight": 1.25 }, @@ -1469,10 +1410,10 @@ { "id": "INytNNGW35A1LfRrBpWxU", "type": "text", - "x": 1073.2739879747762, - "y": 129.82987544409283, - "width": 146.76405334472656, - "height": 22.613951497751323, + "x": 1065.5260707994833, + "y": 128.6368511929685, + "width": 162.2598876953125, + "height": 25, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "#b2f2bb", @@ -1486,15 +1427,15 @@ "index": "b1e", "roundness": null, "seed": 1481045880, - "version": 274, - "versionNonce": 883712632, + "version": 276, + "versionNonce": 101306902, "isDeleted": false, "boundElements": [], - "updated": 1736981706948, + "updated": 1748438380516, "link": null, "locked": false, "text": "External Channel", - "fontSize": 18.091161198201057, + "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", @@ -1539,13 +1480,88 @@ "originalText": "OR", "autoResize": true, "lineHeight": 1.25 + }, + { + "id": "EOC1C6l7kpfOlF48Jw93i", + "type": "text", + "x": 1121.2035355363544, + "y": 174.09997446362837, + "width": 47.88795471191406, + "height": 20, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1g", + "roundness": null, + "seed": 1479607062, + "version": 85, + "versionNonce": 439501590, + "isDeleted": false, + "boundElements": null, + "updated": 1748438418192, + "link": null, + "locked": false, + "text": "Hubble", + "fontSize": 16, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Hubble", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "nKTJ3k3MqRAxII2NNYAMD", + "type": "text", + "x": 871.2595581803973, + "y": 175.09997446362837, + "width": 71.59994506835938, + "height": 20, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1h", + "roundness": null, + "seed": 1286369930, + "version": 234, + "versionNonce": 767165514, + "isDeleted": false, + "boundElements": [], + "updated": 1748438501334, + "link": null, + "locked": false, + "text": "Standard", + "fontSize": 16, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Standard", + "autoResize": true, + "lineHeight": 1.25 } ], "appState": { "gridSize": 20, "gridStep": 5, "gridModeEnabled": false, - "viewBackgroundColor": "#ffffff" + "viewBackgroundColor": "#ffffff", + "lockedMultiSelections": {} }, "files": {} } \ No newline at end of file diff --git a/docs/01-Introduction/img/data-plane.png b/docs/01-Introduction/img/data-plane.png index dbdf73161950aec2ecb91e1668583dfbab5406f4..d391898ca00eb00f8d2c2453184f674b26782157 100644 GIT binary patch literal 144476 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%0Da-&oXFzXh7Y`K)59z97$Ob7qT+~8ii(o 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 K!Uclbp8p3xlQ@I` From 0de070a58810e0d3bf5f8dcf08ecfe5d96e1ea73 Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Wed, 28 May 2025 21:36:11 -0700 Subject: [PATCH 024/448] fix: Remove unnecessary allocations from debug log (#1623) # Description In this hot code path computing the key for the debug log does a bunch of unnecessary string allocations. Refactor to use `zap` lazy serialization so we only incur this cost when debug logging is turned on. ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Deployed with debug logging turned on, logs as expected. ``` retina-agent-q9525 retina ts=2025-05-22T22:50:39.044Z level=debug caller=cache/cache.go:100 msg="pod found for IP" ip=172.26.11.226 pod=platform/thanos-rule-remote-1 retina-agent-q9525 retina ts=2025-05-22T22:50:39.044Z level=debug caller=cache/cache.go:140 msg="pod found for IP" ip=172.26.11.226 pod=platform/thanos-rule-remote-1 retina-agent-q9525 retina ts=2025-05-22T22:50:39.044Z level=debug caller=cache/cache.go:94 msg="pod not found for IP" ip=172.27.12.108 retina-agent-q9525 retina ts=2025-05-22T22:50:39.044Z level=debug caller=cache/cache.go:116 msg="service found for IP" ip=172.27.12.108 svc=platform/thanos-query ``` Signed-off-by: Matthew McKeen --- pkg/common/endpoint.go | 4 ++++ pkg/controllers/cache/cache.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/common/endpoint.go b/pkg/common/endpoint.go index aebbcc7971..d6d9c9037f 100644 --- a/pkg/common/endpoint.go +++ b/pkg/common/endpoint.go @@ -19,6 +19,10 @@ func NewRetinaEndpoint(name, namespace string, ips *IPAddresses) *RetinaEndpoint } } +func (ep *RetinaEndpoint) String() string { + return ep.NamespacedName() +} + func (ep *RetinaEndpoint) DeepCopy() interface{} { ep.RLock() defer ep.RUnlock() diff --git a/pkg/controllers/cache/cache.go b/pkg/controllers/cache/cache.go index c51fa18110..362565c4f4 100644 --- a/pkg/controllers/cache/cache.go +++ b/pkg/controllers/cache/cache.go @@ -153,7 +153,7 @@ func (c *Cache) getObjByIPType(ip string, t objectType) interface{} { // GetObjByIP returns the retina object for the given IP. func (c *Cache) GetObjByIP(ip string) interface{} { if ep := c.GetPodByIP(ip); ep != nil { - c.l.Debug("pod found for IP", zap.String("ip", ip), zap.String("pod Name", ep.Key())) + c.l.Debug("pod found for IP", zap.String("ip", ip), zap.Stringer("pod", ep)) return ep } From ec678531d80e41e5c8603aa206546d22a1168f6b Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 29 May 2025 17:29:21 +0100 Subject: [PATCH 025/448] docs: add information about usage of Annotations and MetricsConfiguration CRD (#1636) # Description This PR adds information about usage of Annotations and MetricsConfiguration CRD. ## Related Issue Fixes #1632 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- docs/02-Installation/03-Config.md | 2 +- docs/03-Metrics/annotations.md | 2 ++ docs/03-Metrics/configuration.md | 2 ++ docs/03-Metrics/modes/modes.md | 6 ++++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/02-Installation/03-Config.md b/docs/02-Installation/03-Config.md index b758337ae0..6b6df2895d 100644 --- a/docs/02-Installation/03-Config.md +++ b/docs/02-Installation/03-Config.md @@ -50,7 +50,7 @@ Apply to both Agent and Operator. * `metricsIntervalDuration`: Interval for gathering metrics (in `time.Duration`). * `enablePodLevel`: Enables gathering of advanced pod-level metrics, attaching pods' metadata to Retina's metrics. * `enableConntrackMetrics`: Enables conntrack metrics for packets and bytes forwarded/received. -* `enableAnnotations`: Enables gathering of metrics for annotated resources. Resources can be annotated with `retina.sh=observe`. Requires the operator and `operator.enableRetinaEndpoint` to be enabled. +* `enableAnnotations`: Enables gathering of metrics for annotated resources. Resources can be annotated with `retina.sh=observe`. Requires the operator and `operator.enableRetinaEndpoint` to be enabled. By enabling annotations, the agent will not use MetricsConfiguration CRD. * `bypassLookupIPOfInterest`: If true, plugins like `packetparser` and `dropreason` will bypass IP lookup, generating an event for each packet regardless. `enableAnnotations` will not work if this is true. * `dataAggregationLevel`: Defines the level of data aggregation for Retina. See [Data Aggregation](../05-Concepts/data-aggregation.md) for more details. diff --git a/docs/03-Metrics/annotations.md b/docs/03-Metrics/annotations.md index fa171020ea..bd4282445c 100644 --- a/docs/03-Metrics/annotations.md +++ b/docs/03-Metrics/annotations.md @@ -9,3 +9,5 @@ You can then add the annotation `retina.sh: observe` to either: - Namespaces (to observe all the Pods in the namespace). An exception: currently all Pods in `kube-system` are always monitored. + +**Note**: If you enable Annotations, you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. diff --git a/docs/03-Metrics/configuration.md b/docs/03-Metrics/configuration.md index d562a339fc..87cd3e80ba 100644 --- a/docs/03-Metrics/configuration.md +++ b/docs/03-Metrics/configuration.md @@ -6,3 +6,5 @@ Via [MetricsConfiguration CRD](../05-Concepts/CRDs/MetricsConfiguration.md), you - Which metrics to include - Which metadata to include for a metric. + +**Note**: If you enable [Annotations](./annotations.md), you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. diff --git a/docs/03-Metrics/modes/modes.md b/docs/03-Metrics/modes/modes.md index ce2d3a4b00..b82bd60bab 100644 --- a/docs/03-Metrics/modes/modes.md +++ b/docs/03-Metrics/modes/modes.md @@ -12,8 +12,10 @@ The larger the cardinality, the more load induced on a Prometheus server for ins | Mode | Description | Scale | Metrics | Configuration | | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------ | | *Basic* | Metrics aggregated by Node. | Metric cardinality proportional to number of nodes. | [Link to Metrics](./basic.md) | [Link to Installation](../../02-Installation/01-Setup.md#basic-mode) | -| *Advanced/Pod-Level with remote context* | Basic metrics plus extra metrics aggregated by source and destination Pod. | Has scale limitations. Metric cardinality is unbounded (proportional to number of source/destination pairs, including external IPs). | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context-with-capture-support) | -| *Advanced/Pod-Level with local context* | Basic metrics plus extra metrics aggregated by "local" Pod (source for outgoing traffic, destination for incoming traffic). Also lets you specify which Pods to observe (create metrics for) with [Annotations](../annotations.md). | Designed for scale. Metric cardinality proportional to number of Pods observed. | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context-with-capture-support) | +| *Advanced/Pod-Level with remote context* | Basic metrics plus extra metrics aggregated by source and destination Pod. | Has scale limitations. Metric cardinality is unbounded (proportional to number of source/destination pairs, including external IPs). | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context-with-capture-support) | +| *Advanced/Pod-Level with local context* | Basic metrics plus extra metrics aggregated by "local" Pod (source for outgoing traffic, destination for incoming traffic). | Designed for scale. Metric cardinality proportional to number of Pods observed. | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context-with-capture-support) | + +Both advanced metric modes let you specify which Pods to observe (create metrics for) by using [Annotations](../annotations.md) or [MetricsConfiguration CRD](../configuration.md). ## Where Do Metrics Come From? From c626b5981fcc2f09253d9554eff84c132ce7f836 Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Thu, 29 May 2025 14:55:29 -0700 Subject: [PATCH 026/448] feat(helm): Allow passing arbitrary env variables to the DaemonSet (#1637) # Description Allows passing arbitrary environment variables to the DaemonSet in the standard Helm chart. ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed No diff between `helm template` with current chart with default values and that from this PR. Diff with provided `env` values shows values added as expected. ``` env: - name: test1 value: test1 - name: test2 value: test2 - name: POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name - name: NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName ``` --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- .../controller/helm/retina/templates/daemonset.yaml | 6 ++++++ .../standard/manifests/controller/helm/retina/values.yaml | 1 + 2 files changed, 7 insertions(+) diff --git a/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml b/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml index 2b7e929421..3574142463 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml @@ -87,6 +87,9 @@ spec: resources: {{- toYaml .Values.resources | nindent 12 }} env: + {{- if .Values.daemonset.container.retina.env -}} + {{ toYaml .Values.daemonset.container.retina.env | nindent 10 }} + {{- end }} - name: POD_NAME valueFrom: fieldRef: @@ -218,6 +221,9 @@ spec: - .\setkubeconfigpath.ps1; ./controller.exe --config ./retina/config.yaml --kubeconfig ./kubeconfig {{- end }} env: + {{- if .Values.daemonset.container.retina.env -}} + {{ toYaml .Values.daemonset.container.retina.env | nindent 10 }} + {{- end }} - name: POD_NAME valueFrom: fieldRef: diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index 032157e17c..6bf0c9cf60 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -98,6 +98,7 @@ daemonset: args: - "--config" - "/retina/config/config.yaml" + env: [] healthProbeBindAddress: ":18081" metricsBindAddress: ":18080" ports: From e2053f6d85ea3f2a2042a6a1c30ac69dc17562a4 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Fri, 30 May 2025 09:52:38 +0100 Subject: [PATCH 027/448] chore(docs): Capture CLI docs (#1639) # Description Update the Setup and Capture docs to be more concise and clear. Restructured the Setup page. Added a `Capture with CRD` page for consistency - a little bit of overlap with the Concepts/CRDs/Capture. Renamed headings under Prometheus and Grafana to add "Configuration". - The setup page had "Next steps: Prometheus & Grafana" at the bottom, even though those were NOT the next steps according to the order of the docs, so removed that text to avoid confusion. ## Related Issue NA ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ### Setup page ![{9A23BD5F-AF49-4FBE-90A1-A3822BC71B3F}](https://github.com/user-attachments/assets/fb775360-3561-4dcc-95b6-0db72e859fde) ### Capture Overview page ![image](https://github.com/user-attachments/assets/85ab22e9-acec-4c4c-9a77-6c3ac3a9f3ee) ### Capture CLI page ![image](https://github.com/user-attachments/assets/5313fc57-969a-4136-822b-38b4bcc06b8e) ### Capture CRD page ![image](https://github.com/user-attachments/assets/e7d7fbc0-c731-46a8-95fd-bd82224b6772) --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Kamil --- docs/02-Installation/01-Setup.md | 42 +++---- docs/02-Installation/04-prometheus.md | 2 +- docs/02-Installation/05-grafana.md | 4 +- docs/04-Captures/01-overview.md | 74 ++---------- docs/04-Captures/02-cli.md | 49 +++++--- docs/04-Captures/03-crd.md | 111 ++++++++++++++++++ ...count.md => 04-managed-storage-account.md} | 34 ++++++ 7 files changed, 214 insertions(+), 102 deletions(-) create mode 100644 docs/04-Captures/03-crd.md rename docs/04-Captures/{03-managed-storage-account.md => 04-managed-storage-account.md} (84%) diff --git a/docs/02-Installation/01-Setup.md b/docs/02-Installation/01-Setup.md index b3fd0dc2ac..b59d92efac 100644 --- a/docs/02-Installation/01-Setup.md +++ b/docs/02-Installation/01-Setup.md @@ -2,8 +2,6 @@ This page provides the instructions on how to install Retina via Helm. -## Installation - The assumption is that a Kubernetes cluster has already been created and we have credentials to access it. >NOTE: In case you want to test out Retina quickly and you have no clusters, you can quickly create one with [kind](https://kind.sigs.k8s.io/) @@ -25,12 +23,12 @@ kubectl cluster-info --context kind-test-retina Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/ ``` -### Requirements +## Requirements - Helm version >= v3.8.0 - Access to a Kubernetes cluster via `kubectl` -### Control Plane and Modes +## Control Plane and Modes The installation of Retina can be configured using different control planes and modes. @@ -40,7 +38,15 @@ If the "Standard" control plane is chosen, different modes are available. The av Modes are not applicable to the Hubble control plane. For metrics related to the Hubble control plane, refer to the [Hubble metrics](../03-Metrics/02-hubble_metrics.md) documentation. -### Basic Mode +## Capture Support + +In order to support the use of the [Capture CRD](../05-Concepts/CRDs/Capture.md), the Standard Control Plane must be used, and the Retina operator pod needs to be running. + +>NOTE: Captures can still be triggered with the [CLI](../04-Captures/02-cli.md) even without the Retina operator pod running. + +Enable the operator with the `--set operator.enabled=true \` flag. + +For example, this is how you could install Retina with the Standard Control Plane and basic metric mode, with the operator. ```shell VERSION=$( curl -sL https://api.github.com/repos/microsoft/retina/releases/latest | jq -r .name) @@ -50,10 +56,15 @@ helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina \ --set image.tag=$VERSION \ --set operator.tag=$VERSION \ --set logLevel=info \ + --set operator.enabled=true \ --set enabledPlugin_linux="\[dropreason\,packetforward\,linuxutil\,dns\]" ``` -### Basic Mode (with Capture support) +## Installation + +### Standard Control Plane + +#### Basic Mode ```shell VERSION=$( curl -sL https://api.github.com/repos/microsoft/retina/releases/latest | jq -r .name) @@ -63,16 +74,10 @@ helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina \ --set image.tag=$VERSION \ --set operator.tag=$VERSION \ --set logLevel=info \ - --set image.pullPolicy=Always \ - --set logLevel=info \ - --set os.windows=true \ - --set operator.enabled=true \ - --set operator.enableRetinaEndpoint=true \ - --skip-crds \ - --set enabledPlugin_linux="\[dropreason\,packetforward\,linuxutil\,dns\,packetparser\]" + --set enabledPlugin_linux="\[dropreason\,packetforward\,linuxutil\,dns\]" ``` -### Advanced Mode with Remote Context (with Capture support) +#### Advanced Mode with Remote Context ```shell VERSION=$( curl -sL https://api.github.com/repos/microsoft/retina/releases/latest | jq -r .name) @@ -92,7 +97,7 @@ helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina \ --set remoteContext=true ``` -### Advanced Mode with Local Context (with Capture support) +#### Advanced Mode with Local Context ```shell VERSION=$( curl -sL https://api.github.com/repos/microsoft/retina/releases/latest | jq -r .name) @@ -112,7 +117,7 @@ helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina \ --set enableAnnotations=true ``` -### Hubble control plane +### Hubble Control Plane ```shell VERSION=$( curl -sL https://api.github.com/repos/microsoft/retina/releases/latest | jq -r .name) @@ -137,8 +142,3 @@ helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina-hubbl --set hubble.tls.auto.certValidityDuration=1 \ --set hubble.tls.auto.schedule="*/10 * * * *" ``` - -## Next Steps: Configuring Prometheus and Grafana - -- [Prometheus](./04-prometheus.md) -- [Grafana](./05-grafana.md) diff --git a/docs/02-Installation/04-prometheus.md b/docs/02-Installation/04-prometheus.md index a5d7e67c20..1fd8d8cebb 100644 --- a/docs/02-Installation/04-prometheus.md +++ b/docs/02-Installation/04-prometheus.md @@ -1,4 +1,4 @@ -# Prometheus +# Configuring Prometheus Prometheus is an open-source system monitoring and alerting toolkit originally built at SoundCloud. It is now a standalone open source project and maintained independently of any company. Prometheus's main features include a multi-dimensional data model, a flexible query language, efficient time series database, and modern alerting approach. For more information, visit the [Prometheus website](https://prometheus.io). diff --git a/docs/02-Installation/05-grafana.md b/docs/02-Installation/05-grafana.md index 4725d61997..2e12c2e125 100644 --- a/docs/02-Installation/05-grafana.md +++ b/docs/02-Installation/05-grafana.md @@ -1,4 +1,4 @@ -# Grafana +# Configuring Grafana Grafana is an open-source platform for monitoring and observability. It allows you to query, visualize, alert on, and explore your metrics no matter where they are stored. For more information, visit the [Grafana open-source section](https://grafana.com/oss/). @@ -6,7 +6,7 @@ Grafana is an open-source platform for monitoring and observability. It allows y Make sure that you're still port-forwarding your server to [localhost:9090](http://localhost:9090) as part of [Prometheus](./04-prometheus.md) setup. Alternatively you can configure your server for some other HTTP endpoint, but that is not covered in the following instructions. -## Configuring Grafana +## Configuration If you followed the steps to install and configure [Prometheus](./04-prometheus.md), you will already have Grafana installed as part of the `kube-prometheus-stack` Helm chart. diff --git a/docs/04-Captures/01-overview.md b/docs/04-Captures/01-overview.md index 3bc3f9104b..f0a7bd21da 100644 --- a/docs/04-Captures/01-overview.md +++ b/docs/04-Captures/01-overview.md @@ -1,78 +1,28 @@ # Overview -Retina Capture allows users to capture network traffic/metadata for specified Nodes/Pods. +Retina Capture allows users to perform distributed packet captures across the cluster, based on specified Nodes/Pods and other supported filters. -Captures are on-demand and can be output to persistent storage such as the host filesystem, a storage blob, etc. - -## Usage +Captures are on-demand and can be output to persistent storage such as the host filesystem, a storage blob or PVC. There are two methods for triggering a Capture: -- [CLI command](#option-1-retina-cli) -- [CRD/YAML configuration](#option-2-capture-crd-custom-resource-definition) +- [CLI command](./02-cli.md) +- [CRD/YAML configuration](./03-crd.md) -### Option 1: Retina CLI +It is also possible to set up a managed storage account when setting up Retina. -> Prerequisite: [Install Retina CLI](../02-Installation/02-CLI.md) +- [Managed Storage Account](../04-Captures/04-managed-storage-account.md#setup) -The command syntax is `kubectl retina capture create [--flags]`. +## Capture Jobs -Refer to the [Capture Command](../04-Captures/02-cli.md) documentation for more details. +A packet capture can cover multiple Nodes. This can be explicitly specified by using `node-selectors`. It could also be implicit - for example when using `pod-selectors` and the targetted Pods are hosted across different Nodes. -This example captures network traffic for all Linux Nodes, storing the output in the folder */mnt/capture* on each Node. +Whenever a capture is initiated, a Kubernetes Job is created on each relevant Node. -```shell -kubectl retina capture create --name capture-test --host-path /mnt/capture --node-selectors "kubernetes.io/os=linux" -``` +The Job's worker Pod runs for the specified duration, captures and wraps the network information into a tarball. It then copies the tarball to the specified output location(s). -For each Capture, a Kubernetes Job is created for each relevant Node (the Node could be selected and/or could be hosting a selected Pod). -The Job's worker Pod runs for the specified duration, captures and wraps the network information into a tarball, and copies the tarball to the specified output location(s). As a special case, a Kubernetes secret will be created containing a storage blob SAS for security concerns, then mounted to the Pod. -A random hashed name is assigned to each Retina Capture to uniquely label it. - -![Overview of Retina Capture without operator](img/capture-architecture-without-operator.png "Overview of Retina Capture without operator") - -### Option 2: Capture CRD (Custom Resource Definition) - -> Prerequisite: [Install Retina](../02-Installation/01-Setup.md) **with capture support**. - -Refer to the [Capture CRD](../05-Concepts/CRDs/Capture.md) documentation for more details. - -#### Managed Storage Account - -To simplify the user experience, a managed storage account can be configured when setting up Retina. Instructions for this are provided [here](../04-Captures/03-managed-storage-account.md#setup). - -This example creates a Capture and stores the Capture artifacts into a storage account specified by Blob SAS URL. - -Create a secret to store blob SAS URL (and store it in blob-upload-url.txt): - -```bash -kubectl create secret generic blob-sas-url --from-file=blob-upload-url=./blob-upload-url.txt -``` - -Create a Capture specifying the secret created as blobUpload, this example will also store the artifact on the node host path. - -```yaml -apiVersion: retina.sh/v1alpha1 -kind: Capture -metadata: - name: capture-test -spec: - captureConfiguration: - captureOption: - duration: 30s - captureTarget: - nodeSelector: - matchLabels: - kubernetes.io/hostname: aks-nodepool1-11396069-vmss000000 - outputConfiguration: - hostPath: "/tmp/retina" - blobUpload: blob-sas-url -``` - -More Retina Capture samples can be found [here](https://github.com/microsoft/retina/tree/main/samples/capture). - -Similarly to Option 1, a Kubernetes Job is created for each relevant Node. +A random hashed name is assigned to each Retina Capture job to uniquely label it. For example, a capture named `sample-capture` could result in a job called `sample-capture-s7n8q`. -![Overview of Retina Capture with operator](img/capture-architecture-with-operator.png "Overview of Retina Capture with operator") +Corresponding architecture diagrams are present within the [CLI command](./02-cli.md) and [CRD/YAML configuration](./03-crd.md) docs. diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index 19e3b627a6..50d97c9008 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -1,16 +1,30 @@ # Capture with Retina CLI -The capture command in Retina allows users to capture network traffic and metadata for the capture target, and send the data to the location defined by output configuration. +This page describes how the Retina CLI works in the context of performing packet captures. -> NOTE: captures can also be performed with a [Capture CRD](../05-Concepts/CRDs/Capture.md) after [installing Retina](../02-Installation/01-Setup.md) **with capture support**. +The use of the Retina CLI to perform captures does **NOT** require the Retina operator pod to be running. -## Capture Create +See the [overview](./01-overview.md#capture-jobs) for a description of how the capture jobs are created. + +![Overview of Retina Capture without operator](img/capture-architecture-without-operator.png "Overview of Retina Capture without operator") + +## Prerequisites + +- [Install Retina CLI](../02-Installation/02-CLI.md) + +## Operations + +### Capture Create `kubectl retina capture create [--flags]` creates a Capture with underlying Kubernetes jobs. -### Selecting a Target +#### Selecting a Target + +The target indicates where the packet capture will be performed. This can be set via the following flags: -The target indicates where the packet capture will be performed. This can be set via `--node-selectors`, `--node-names`, `--pod-selectors` and `--namespace-selectors` flags. Run `kubectl retina capture -h` for further details based on the Retina CLI version installed on your environment. +- `--node-selectors` +- `--node-names` +- `--pod-selectors` and `--namespace-selectors` (pairs) Note that Node Selectors are not compatible with Pod Selectors & Namespace Selectors pairs and the capture will not go through if all are populated. @@ -18,7 +32,7 @@ If nothing is set, `kubectl retina capture create` will use `--node-selectors` w You can find [target selection examples](#target-selection) below. -### Configuring the Output Location +#### Configuring the Output Location The output configuration indicates the location where the capture will be stored. At least one location needs to be specified. This can either be the host path on the node, or a remote storage option. @@ -26,16 +40,17 @@ Blob-upload requires a Blob Shared Access Signature (SAS) with the write permiss You can find [output configuration examples](#output-configuration) below. -### Stopping a Capture +#### Stopping a Capture The Capture can be stopped in a number of ways: -- In a given time, by the `duration` flag, or when the file reaches the maximum allowed file size defined by the `max-size` flag. When both are specified, the capture will stop whenever **either condition is first met**. +- In a given time, by the `duration` flag, or when the file reaches the maximum allowed file size defined by the `max-size` flag. + - When both are specified, the capture will stop whenever **either condition is first met**. - On demand by [deleting the capture](#capture-delete) before the specified conditions meets. The network traffic will be uploaded to the specified output location. -### Flags +#### Flags | Flag | Type | Default | Description | Notes | |-----------------------|------------|----------|-----------------------------------------------------------------------------|-------| @@ -66,9 +81,9 @@ The network traffic will be uploaded to the specified output location. | `s3-secret-access-key`| string | "" | S3 access secret key to upload capture files. | | | `tcpdump-filter` | string | "" | Raw tcpdump flags. Available tcpdump filters can be found in the [TCPDUMP MAN PAGE](https://www.tcpdump.org/manpages/tcpdump.1.html). | Only works on Linux. Includes only tcpdump flags, for boolean expressions, please use include/exclude filters. | -### Examples +#### Examples -#### Target Selection +##### Target Selection Node Selectors @@ -95,7 +110,7 @@ kubectl retina capture create \ --namespace-selectors="kubernetes.io/metadata.name=kube-system" ``` -#### Output Configuration +##### Output Configuration Host Path @@ -143,7 +158,7 @@ kubectl retina capture create \ --s3-secret-access-key "your-secret-access-key" ``` -#### Capture Filters +##### Capture Filters Include / Exclude Filters @@ -162,7 +177,7 @@ kubectl retina capture create \ --tcpdump-filter="udp port 53" ``` -## Capture Delete +### Capture Delete Deleting the capture job before either of the terminating conditions have been met will stop the capture. @@ -174,7 +189,7 @@ Example: kubectl retina capture delete --name retina-capture-zlx5v ``` -## Capture List +### Capture List To get a list of the captures you can run `kubectl retina capture list` to get the captures in a specific namespace or in all namespaces. @@ -200,7 +215,9 @@ tar -xvf retina-capture-aks-nodepool1-41844487-vmss000000-20230320013600UTC.tar. ### Name pattern of the tarball -the tarball take such name pattern, `$(capturename)-$(hostname)-$(date +%Y%m%d%H%M%S%Z).tar.gz`, for example, `retina-capture-aks-nodepool1-41844487-vmss000000-20230313101436UTC.tar.gz`. +The tarballs take the following name pattern, `$(capturename)-$(hostname)-$(date +%Y%m%d%H%M%S%Z).tar.gz`. + +- e.g. `retina-capture-aks-nodepool1-41844487-vmss000000-20230313101436UTC.tar.gz` ### File and directory structure inside the tarball diff --git a/docs/04-Captures/03-crd.md b/docs/04-Captures/03-crd.md new file mode 100644 index 0000000000..3493f49b85 --- /dev/null +++ b/docs/04-Captures/03-crd.md @@ -0,0 +1,111 @@ +# Capture with CRD + +This page describes how the Retina Capture CRD works. + +See the [overview](./01-overview.md/#capture-jobs) for a description of how the capture jobs are created. + +![Overview of Retina Capture with operator](img/capture-architecture-with-operator.png "Overview of Retina Capture with operator") + +## Prerequisites + +- [Install Retina](../02-Installation/01-Setup.md/#capture-support) **with capture support**. + +## Usage + +You must create a YAML manifest file with the desired specifications and apply it to the cluster using `kubectl apply`. + +- If successful, the capture job should spin up after you apply. +- If not successful, no job will spin up. You can troubleshoot by checking the status of the CRD with `kubectl get capture -o yaml`. + +The full specification for the Capture CRD can be found in the [Capture CRD file](https://github.com/microsoft/retina/blob/main/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml). + +Refer to the [Capture CRD](../05-Concepts/CRDs/Capture.md) page for more details. + +```shell +# Install Retina with Standard Control Plane and Operator enabled +> VERSION=$( curl -sL https://api.github.com/repos/microsoft/retina/releases/latest | jq -r .name) +helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina \ + --version $VERSION \ + --namespace kube-system \ + --set image.tag=$VERSION \ + --set operator.tag=$VERSION \ + --set logLevel=info \ + --set operator.enabled=true \ + --set enabledPlugin_linux="\[dropreason\,packetforward\,linuxutil\,dns\]" + +Release "retina" does not exist. Installing it now. +Pulled: ghcr.io/microsoft/retina/charts/retina:v0.0.33 +Digest: sha256:0d647b8c5090725684ad9bd0c9c988eccd4ee3cbf06a08a7270f362236057bd0 +NAME: retina +LAST DEPLOYED: Fri May 30 09:01:57 2025 +NAMESPACE: kube-system +STATUS: deployed +REVISION: 1 +NOTES: +1. Installing retina service using helm: helm install retina ./deploy/standard/manifests/controller/helm/retina/ --namespace kube-system --dependency-update +2. Cleaning up/uninstalling/deleting retina and dependencies related: + helm uninstall retina -n kube-system + +# Apply the Capture configuration +> kubectl apply -f capture.yaml +capture.retina.sh/hubble-cp-capture created + +# View the jobs which got created +> kubectl get jobs +NAME STATUS COMPLETIONS DURATION AGE +standard-cp-capture-8r8sf Complete 1/1 11s 4m31s +standard-cp-capture-sdtd7 Complete 1/1 11s 4m31s +``` + +## Examples + +Node Selectors and Host Path output target + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: example-node-selectors +spec: + captureConfiguration: + captureOption: + duration: "5s" + maxCaptureSize: 100 + packetSize: 1500 + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/os: linux + outputConfiguration: + hostPath: /captures +``` + +Include / Exclude filters + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: example-include-exclude-filters +spec: + captureConfiguration: + captureOption: + duration: "5s" + maxCaptureSize: 100 + packetSize: 1500 + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/os: linux + filters: + include: + - 10.224.0.42:80 + - 10.224.0.33:8080 + exclude: + - 10.224.0.26:80 + - 10.224.0.34:8080 + outputConfiguration: + hostPath: /captures +``` + +Additional examples can also be found in the [GitHub capture samples](https://github.com/microsoft/retina/tree/main/samples/capture). diff --git a/docs/04-Captures/03-managed-storage-account.md b/docs/04-Captures/04-managed-storage-account.md similarity index 84% rename from docs/04-Captures/03-managed-storage-account.md rename to docs/04-Captures/04-managed-storage-account.md index 11c5edca14..82cb02b375 100644 --- a/docs/04-Captures/03-managed-storage-account.md +++ b/docs/04-Captures/04-managed-storage-account.md @@ -1,5 +1,39 @@ # Managed Storage Account +To simplify the user experience, a managed storage account can be configured when setting up Retina. + +## Example + +This example creates a Capture and stores the Capture artifacts into a storage account specified by Blob SAS URL. + +- Create a secret to store blob SAS URL (and store it in blob-upload-url.txt): + +```bash +kubectl create secret generic blob-sas-url --from-file=blob-upload-url=./blob-upload-url.txt +``` + +- Create a Capture YAML configuration specifying the secret created as blobUpload, this example will also store the artifact on the node host path. + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: capture-test +spec: + captureConfiguration: + captureOption: + duration: 30s + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/hostname: aks-nodepool1-11396069-vmss000000 + outputConfiguration: + hostPath: "/tmp/retina" + blobUpload: blob-sas-url +``` + +More Retina Capture samples can be found [here](https://github.com/microsoft/retina/tree/main/samples/capture). + ## Motivation Retina Capture helps customers capture network packets on Kuberentes cluster to debug network issues. Before Retina Capture can debug the packets, Retina Capture can store the network packets and the customers need to download the packets from Retina Capture supported locations with tools like Wireshark. From f5255405758db24b25f6bb4a31e3ee14f0b4e955 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 30 May 2025 10:05:46 +0100 Subject: [PATCH 028/448] chore(agent): Allow agent to watch endpoints on Hubble CP (#1641) # Description Please provide a brief description of the changes made in this pull request. ## Related Issue Prevent this issue when running on Cilium CNI and no operator enabled ``` ts=2025-05-30T08:34:19.360Z level=warn caller=logrus-zap-hook@v0.1.0/zap.go:51 msg="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=klog ts=2025-05-30T08:34:19.360Z level=error caller=k8s/watcher_linux.go:51 msg="Error watching k8s resource" subsys=k8s-watcher resource=v2.CiliumEndpoint underlyingError="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v2.CiliumEndpoint: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" ts=2025-05-30T08:34:24.685Z level=warn caller=logrus-zap-hook@v0.1.0/zap.go:51 msg="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=klog ts=2025-05-30T08:34:24.685Z level=error caller=k8s/watcher_linux.go:51 msg="Error watching k8s resource" resource=v2.CiliumEndpoint subsys=k8s-watcher underlyingError="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v2.CiliumEndpoint: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" ts=2025-05-30T08:34:27.605Z level=info caller=ciliumeventobserver/ciliumeventobserver_linux.go:146 msg="Connected to cilium monitor" ts=2025-05-30T08:34:36.368Z level=warn caller=logrus-zap-hook@v0.1.0/zap.go:51 msg="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=klog ts=2025-05-30T08:34:36.368Z level=error caller=k8s/watcher_linux.go:51 msg="Error watching k8s resource" underlyingError="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v2.CiliumEndpoint: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" resource=v2.CiliumEndpoint subsys=k8s-watcher ts=2025-05-30T08:34:45.633Z level=error caller=apiserver/apiserver.go:120 msg="failed to initialize new cache" error="failed to retrieve ips from kubernetes endpoint: retrieving kubernetes endpoint: endpoints \"kubernetes\" is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot get resource \"endpoints\" in API group \"\" in the namespace \"default\"" ts=2025-05-30T08:34:45.634Z level=error caller=watchermanager/watchermanager.go:76 msg="refresh failed" error="failed to retrieve ips from kubernetes endpoint: retrieving kubernetes endpoint: endpoints \"kubernetes\" is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot get resource \"endpoints\" in API group \"\" in the namespace \"default\"" ts=2025-05-30T08:34:51.451Z level=warn caller=logrus-zap-hook@v0.1.0/zap.go:51 msg="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=klog ts=2025-05-30T08:34:51.452Z level=error caller=k8s/watcher_linux.go:51 msg="Error watching k8s resource" underlyingError="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v2.CiliumEndpoint: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=k8s-watcher resource=v2.CiliumEndpoint ts=2025-05-30T08:35:17.368Z level=warn caller=logrus-zap-hook@v0.1.0/zap.go:51 msg="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=klog ts=2025-05-30T08:35:17.368Z level=error caller=k8s/watcher_linux.go:51 msg="Error watching k8s resource" resource=v2.CiliumEndpoint subsys=k8s-watcher underlyingError="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v2.CiliumEndpoint: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" ts=2025-05-30T08:35:48.126Z level=warn caller=logrus-zap-hook@v0.1.0/zap.go:51 msg="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" subsys=klog ts=2025-05-30T08:35:48.126Z level=error caller=k8s/watcher_linux.go:51 msg="Error watching k8s resource" subsys=k8s-watcher underlyingError="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v2.CiliumEndpoint: failed to list *v2.CiliumEndpoint: ciliumendpoints.cilium.io is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"ciliumendpoints\" in API group \"cilium.io\" at the cluster scope" resource=v2.CiliumEndpoint ts=2025-05-30T08:36:15.604Z level=info caller=endpointmanager/manager.go:588 msg="regenerating all endpoints" subsys=endpoint-manager reason="periodic endpoint regeneration" ``` ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .../retina/templates/agent/clusterrole.yaml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml index bd60f37cd0..e2331c5d9f 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml @@ -22,7 +22,16 @@ rules: - get - list - watch - {{- if .Values.operator.enabled }} + - apiGroups: + - cilium.io + resources: + - ciliumnodes + - ciliumidentities + - ciliumendpoints + verbs: + - get + - list + - watch - apiGroups: - "" resources: @@ -32,6 +41,7 @@ rules: - get - list - watch + {{- if .Values.operator.enabled }} - apiGroups: - retina.io resources: @@ -78,16 +88,6 @@ rules: - get - list - watch - - apiGroups: - - cilium.io - resources: - - ciliumnodes - - ciliumidentities - - ciliumendpoints - verbs: - - get - - list - - watch {{- end }} {{- end}} From 033b986c6d9ad6ddd71049cbd77c81ded101e187 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Fri, 30 May 2025 11:23:14 +0100 Subject: [PATCH 029/448] docs: Update development documentation for clarity and completeness (#1634) # Description Update documentation for development contributions ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Co-authored-by: Simone Rodigari <32323373+SRodi@users.noreply.github.com> --- docs/08-Contributing/02-development.md | 56 +++++++++++++++++--------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/docs/08-Contributing/02-development.md b/docs/08-Contributing/02-development.md index 051cbacfc8..7486283de5 100644 --- a/docs/08-Contributing/02-development.md +++ b/docs/08-Contributing/02-development.md @@ -1,5 +1,7 @@ # Development +This document provides steps to set up your dev environment and start contributing to the Retina project. You can find the complete documentation on [retina.sh](https://retina.sh) + ## Quick start Retina uses a forking workflow. To contribute, fork the repository and create a branch for your changes. @@ -8,13 +10,16 @@ The easiest way to set up your Development Environment is to use the provided Gi ## Environment Config +Below is a list of required tools and dependencies you need to set up your local development environment for Retina. + - [Go](https://go.dev/doc/install) - [Docker](https://docs.docker.com/engine/install/) - [Helm](https://helm.sh/docs/intro/install) - jq: `sudo apt install jq` -- Fork the repository - If you want to use [ghcr.io](https://github.com/features/packages) as container registry, login following instructions [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic) +Once you have set up your environment fork the repository and create a branch for your changes. + ### LLVM/Clang Installation To manually configure your DevEnv you will need `llvm-strip` and `clang`. @@ -49,13 +54,6 @@ sudo ln -s /usr/bin/llvm-strip-16 /usr/bin/llvm-strip ## Building and Testing -### Test - -```bash -make test # run unit-test locally -make test-image # run tests in docker container -``` - ### Build Generate all mocks and BPF programs: @@ -73,7 +71,7 @@ make retina To build a `retina-agent` container image with specific tag: ```bash -make retina-image # also pushes to image registy +make retina-image # also pushes to image registry make retina-operator-image ``` @@ -95,11 +93,18 @@ debug packetforward Received PacketForward data {"Data": "IngressBytes:8 ... ``` +### Test + +```bash +make test # run unit-tests locally +make test-image # run tests in docker container +``` + ### Publishing Images and Charts To publish images to GHCR in your forked repository, simply push to `main`, or publish a tag. The `container-publish` action will run automatically and push images to your GitHub packages registry. -These registries are private by default; to pull images from your registry anonymously, [navigate to "Package Settings" for each publish image repository and set the visibility to "Public"](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#configuring-access-to-packages-for-your-personal-account). +These registries are private by default; to pull images from your registry anonymously, [navigate to "Package Settings" for each published image repository and set the visibility to "Public"](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#configuring-access-to-packages-for-your-personal-account). Alternatively, configure authenticated access to your registry using a [GitHub Personal Access Token](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-to-the-container-registry). @@ -180,12 +185,6 @@ Uninstall `Retina`: make helm-uninstall ``` -## Updating Documentation - -The documentation available on [retina.sh](https://retina.sh) can be found within the [docs](https://github.com/microsoft/retina/tree/main/docs) folder in the repository. - -The diagrams used are created with [Excalidraw](https://excalidraw.com/). The source `.excalidraw` files are stored within the repository, alongside their `.png` equivalent. - ## Opening a Pull Request When you're ready to open a pull request, please ensure that your branch is up-to-date with the `main` branch, updates relevant docs and tests, and passes all tests and lints. @@ -193,15 +192,34 @@ When you're ready to open a pull request, please ensure that your branch is up-t ### Cryptographic Signing of Commits In order to certify the provenance of commits and defend against impersonation, we require that all commits be cryptographically signed. -Documentation for setting up Git and Github to sign your commits can be found [here](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). +Documentation for setting up Git and GitHub to sign your commits can be found [here](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). Additional information about Git's use of GPG can be found [here](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) > To configure your Git client to sign commits by default for a local repository, run `git config --add commit.gpgsign true`. For **GitHub Codespaces** users, please follow [this doc](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-gpg-verification-for-github-codespaces) to configure GitHub to automatically use GPG to sign commits you make in your Codespaces. -### Developers Certificate of Origin (DCO) +### Developer Certificate of Origin (DCO) -Contributions to Retina must contain a Developers Certificate of Origin within their constituent commits. +Contributions to Retina must contain a Developer Certificate of Origin within their constituent commits. This can be accomplished by providing a `-s` flag to `git commit` as documented [here](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s). This will add a `Signed-off-by` trailer to your Git commit, affirming your acceptance of the Contributor License Agreement. + +### Updating Documentation + +The documentation available on [retina.sh](https://retina.sh) can be found within the [docs](https://github.com/microsoft/retina/tree/main/docs) folder in the repository. + +The diagrams used are created with [Excalidraw](https://excalidraw.com/). The source `.excalidraw` files are stored within the repository, alongside their `.png` equivalent. + +### GitHub issues and Good First Issue + +You can find the open issues on the repo's [GitHub issues board](https://github.com/microsoft/retina/issues) +If you are a first-time contributor, you can find the issues that are suitable for newcomers by finding the [issues labeled as "good first issue"](https://github.com/microsoft/retina/labels/good%20first%20issue) + +### Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +### License + +See [LICENSE](../../LICENSE). From 0fe81b88f24620f9c6673af2e92df1ab3b3488ed Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Fri, 30 May 2025 12:17:57 +0100 Subject: [PATCH 030/448] docs: Fix broken links (#1643) # Description Fixing broken links added in https://github.com/microsoft/retina/pull/1639 ## Related Issue NA ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Kamil --- docs/03-Metrics/modes/modes.md | 4 ++-- docs/04-Captures/03-crd.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/03-Metrics/modes/modes.md b/docs/03-Metrics/modes/modes.md index b82bd60bab..46742db0fc 100644 --- a/docs/03-Metrics/modes/modes.md +++ b/docs/03-Metrics/modes/modes.md @@ -12,8 +12,8 @@ The larger the cardinality, the more load induced on a Prometheus server for ins | Mode | Description | Scale | Metrics | Configuration | | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------ | | *Basic* | Metrics aggregated by Node. | Metric cardinality proportional to number of nodes. | [Link to Metrics](./basic.md) | [Link to Installation](../../02-Installation/01-Setup.md#basic-mode) | -| *Advanced/Pod-Level with remote context* | Basic metrics plus extra metrics aggregated by source and destination Pod. | Has scale limitations. Metric cardinality is unbounded (proportional to number of source/destination pairs, including external IPs). | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context-with-capture-support) | -| *Advanced/Pod-Level with local context* | Basic metrics plus extra metrics aggregated by "local" Pod (source for outgoing traffic, destination for incoming traffic). | Designed for scale. Metric cardinality proportional to number of Pods observed. | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context-with-capture-support) | +| *Advanced/Pod-Level with remote context* | Basic metrics plus extra metrics aggregated by source and destination Pod. | Has scale limitations. Metric cardinality is unbounded (proportional to number of source/destination pairs, including external IPs). | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context) | +| *Advanced/Pod-Level with local context* | Basic metrics plus extra metrics aggregated by "local" Pod (source for outgoing traffic, destination for incoming traffic). | Designed for scale. Metric cardinality proportional to number of Pods observed. | [Link to Metrics](./advanced.md) | [Link to Installation](../../02-Installation/01-Setup.md#advanced-mode-with-local-context) | Both advanced metric modes let you specify which Pods to observe (create metrics for) by using [Annotations](../annotations.md) or [MetricsConfiguration CRD](../configuration.md). diff --git a/docs/04-Captures/03-crd.md b/docs/04-Captures/03-crd.md index 3493f49b85..3212aba1e6 100644 --- a/docs/04-Captures/03-crd.md +++ b/docs/04-Captures/03-crd.md @@ -2,13 +2,13 @@ This page describes how the Retina Capture CRD works. -See the [overview](./01-overview.md/#capture-jobs) for a description of how the capture jobs are created. +See the [overview](./01-overview.md#capture-jobs) for a description of how the capture jobs are created. ![Overview of Retina Capture with operator](img/capture-architecture-with-operator.png "Overview of Retina Capture with operator") ## Prerequisites -- [Install Retina](../02-Installation/01-Setup.md/#capture-support) **with capture support**. +- [Install Retina](../02-Installation/01-Setup.md#capture-support) **with capture support**. ## Usage From 0625ffcc6b8750aea720df2f6532af3236dd4655 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Fri, 30 May 2025 17:02:16 +0100 Subject: [PATCH 031/448] docs: Remove duplicate docs (#1644) # Description Removing duplicate docs from the Development page, which are already present on the Overview. ## Related Issue NA ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [] I have added tests, if applicable. ## Screenshots ![image](https://github.com/user-attachments/assets/af433140-6418-4f58-b4f1-585e0e1bb15f) --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Kamil Co-authored-by: Kamil --- docs/08-Contributing/02-development.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/08-Contributing/02-development.md b/docs/08-Contributing/02-development.md index 7486283de5..1ef241a16f 100644 --- a/docs/08-Contributing/02-development.md +++ b/docs/08-Contributing/02-development.md @@ -215,11 +215,3 @@ The diagrams used are created with [Excalidraw](https://excalidraw.com/). The so You can find the open issues on the repo's [GitHub issues board](https://github.com/microsoft/retina/issues) If you are a first-time contributor, you can find the issues that are suitable for newcomers by finding the [issues labeled as "good first issue"](https://github.com/microsoft/retina/labels/good%20first%20issue) - -### Code of Conduct - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -### License - -See [LICENSE](../../LICENSE). From bad4dd9e60e45d573e2f3a2a9dd6775faf889f3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 12:43:28 -0400 Subject: [PATCH 032/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.9.0 to 1.10.0 (#1605) Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.9.0 to 1.10.0.

Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/azidentity's releases.

sdk/azidentity/v1.10.0

1.10.0 (2025-05-14)

Features Added

  • DefaultAzureCredential reads environment variable AZURE_TOKEN_CREDENTIALS to enable a subset of its credentials:
    • dev selects AzureCLICredential and AzureDeveloperCLICredential
    • prod selects EnvironmentCredential, WorkloadIdentityCredential and ManagedIdentityCredential
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/azidentity&package-manager=go_modules&previous-version=1.9.0&new-version=1.10.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 3b4e0dcffc..c28ac9d04d 100644 --- a/go.mod +++ b/go.mod @@ -210,9 +210,9 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.37.0 // indirect + golang.org/x/crypto v0.38.0 // indirect golang.org/x/mod v0.24.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.31.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect @@ -241,11 +241,11 @@ require ( github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.39.0 // indirect + golang.org/x/net v0.40.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect golang.org/x/sync v0.14.0 golang.org/x/sys v0.33.0 - golang.org/x/term v0.31.0 // indirect + golang.org/x/term v0.32.0 // indirect google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 @@ -262,7 +262,7 @@ require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 diff --git a/go.sum b/go.sum index 0957e2c27c..aefd3a08c4 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= @@ -1279,8 +1279,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1 h1:+o7rrBoj54t8fqQSmnwRLdLzp5 github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1/go.mod h1:bWIjbxmrAk9eKGg9LSko3oQefoYGyWV4xzNS55PgL60= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 h1:LJF39lvUagUpKfL2/gZIp5vHv3AwXt9zOZ/Xual/CzI= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1/go.mod h1:VAY1vDpD/dLwfw/wU5SsexXNhCO9DjhRoGkmJeFONoE= -github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= -github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= @@ -1619,8 +1619,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1688,8 +1688,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= @@ -1784,8 +1784,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1797,8 +1797,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 59014f78ed3d916f720d13778e0a7f3d5866f705 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 22:58:44 -0400 Subject: [PATCH 033/448] deps: bump github.com/prometheus/common from 0.63.0 to 0.64.0 (#1604) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.63.0 to 0.64.0.
Release notes

Sourced from github.com/prometheus/common's releases.

v0.64.0

What's Changed

New Contributors

Full Changelog: https://github.com/prometheus/common/compare/v0.63.0...v0.64.0

Commits
  • 6a35e02 build(deps): bump golang.org/x/oauth2 from 0.29.0 to 0.30.0 (#788)
  • 487c180 refactor(promslog): make NewNopLogger() wrapper around New() (#783)
  • b8eddd7 build(deps): bump golang.org/x/net from 0.38.0 to 0.39.0 (#786)
  • 8048031 build(deps): bump golang.org/x/oauth2 from 0.28.0 to 0.29.0 (#785)
  • 4ca345a build(deps): bump github.com/prometheus/client_model from 0.6.1 to 0.6.2 (#784)
  • 633961f Merge pull request #787 from prometheus/repo_sync
  • 8c1fb2e Update common Prometheus files
  • 8de85c2 Merge pull request #739 from prometheus/beorn7/log
  • 31ee791 promslog: Use the default timezone (again)
  • 318ef65 build(deps): bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#776)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/common&package-manager=go_modules&previous-version=0.63.0&new-version=0.64.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index c28ac9d04d..62adff1267 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect - golang.org/x/oauth2 v0.28.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.14.0 golang.org/x/sys v0.33.0 golang.org/x/term v0.32.0 // indirect @@ -295,8 +295,8 @@ require ( github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.63.0 + github.com/prometheus/client_model v0.6.2 + github.com/prometheus/common v0.64.0 github.com/safchain/ethtool v0.6.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 diff --git a/go.sum b/go.sum index aefd3a08c4..8c5b063457 100644 --- a/go.sum +++ b/go.sum @@ -1252,12 +1252,12 @@ github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= +github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -1692,8 +1692,8 @@ golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 1a342637e8e716f160bbbd1e14dd08c661398006 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 12:32:25 -0400 Subject: [PATCH 034/448] deps: bump github.com/safchain/ethtool from 0.6.0 to 0.6.1 (#1651) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/safchain/ethtool](https://github.com/safchain/ethtool) from 0.6.0 to 0.6.1.
Release notes

Sourced from github.com/safchain/ethtool's releases.

v0.6.1

What's Changed

New Contributors

Full Changelog: https://github.com/safchain/ethtool/compare/v0.6.0...v0.6.1

Commits
  • f9520b6 fix: add StatsWithBuffer method for optimized stats retrieval and maintain ba...
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/safchain/ethtool&package-manager=go_modules&previous-version=0.6.0&new-version=0.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 62adff1267..7c0f7a389e 100644 --- a/go.mod +++ b/go.mod @@ -297,7 +297,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.64.0 - github.com/safchain/ethtool v0.6.0 + github.com/safchain/ethtool v0.6.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 diff --git a/go.sum b/go.sum index 8c5b063457..d169779ec3 100644 --- a/go.sum +++ b/go.sum @@ -1301,8 +1301,8 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a h1:np2nR32/A/VcOG9Hn+IOPA8kMk1gbBzK5LpSsgq5pJI= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a/go.mod h1:wiP6GQ2T378F+YIyuNw7yXtBxJZR+fqrrn1Z6UHZi0Q= -github.com/safchain/ethtool v0.6.0 h1:38VicU4p9ewEQFLemCFiGsknSMn7S3xXEzxaGYTjcn4= -github.com/safchain/ethtool v0.6.0/go.mod h1:JzoNbG8xeg/BeVeVoMCtCb3UPWoppZZbFpA+1WFh+M0= +github.com/safchain/ethtool v0.6.1 h1:mhRnXE1H8fV8TTXh/HdqE4tXtb57r//BQh5pPYMuM5k= +github.com/safchain/ethtool v0.6.1/go.mod h1:JzoNbG8xeg/BeVeVoMCtCb3UPWoppZZbFpA+1WFh+M0= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= From 086d4dc1c1a38cbb1e2ed50360a130f8a98f140e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 11:00:00 -0400 Subject: [PATCH 035/448] chore(deps): bump the npm_and_yarn group across 1 directory with 1 update (#1653) Bumps the npm_and_yarn group with 1 update in the /site directory: [tar-fs](https://github.com/mafintosh/tar-fs). Updates `tar-fs` from 2.1.2 to 3.0.9
Commits

Updates `tar-fs` from 3.0.8 to 3.0.9
Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 1c3345cdaf..967bc786d3 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -13594,9 +13594,9 @@ } }, "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -15801,9 +15801,9 @@ } }, "node_modules/tar-fs": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", - "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", + "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", "license": "MIT", "dependencies": { "pump": "^3.0.0", From 3223925df01a85c5ea10b654be70fe3446679cfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 11:00:29 -0400 Subject: [PATCH 036/448] deps: bump aquasecurity/trivy-action from 0.30.0 to 0.31.0 (#1655) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.30.0 to 0.31.0.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.31.0

What's Changed

New Contributors

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.30.0...0.31.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.30.0&new-version=0.31.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 39c6eba598..ff420536d4 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -30,7 +30,7 @@ jobs: echo "TAG=$(make version)" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 + uses: aquasecurity/trivy-action@76071ef0d7ec797419534a183b498b4d6366cf37 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From 2eca8c0d6495a6ab388bff58e9a3d887f5ad7c58 Mon Sep 17 00:00:00 2001 From: Ritwik Ranjan Date: Wed, 4 Jun 2025 13:29:21 -0400 Subject: [PATCH 037/448] feat: update ethtool dependency and modify Stats method to use buffer (#1640) # Description This pull request updates the `ethtool` dependency to version `v0.6.1` and introduces significant changes to the `EthtoolInterface` implementation and related code. The most notable updates include replacing the `Stats` method with `StatsWithBuffer`, modifying constructors and functions to handle additional buffer parameters, and updating tests accordingly. ### Dependency Update: * Updated `ethtool` dependency from version `v0.6.0` to `v0.6.1` in `go.mod`. ### Changes to `EthtoolInterface`: * Replaced the `Stats` method with `StatsWithBuffer`, which accepts additional buffer parameters (`gstring` and `stats`) for improved handling of interface statistics. [[1]](diffhunk://#diff-07973045315381e9cfea6512cdcb566c022108b90e3df891715422ca3598735cL29-R36) [[2]](diffhunk://#diff-ab186a8a488c84ccab2df9bfed9f5c0412cf4c45ff62c184a7b661e0873add61L109-R110) ### Updates to Constructors and Functions: * Modified the `NewEthtoolReader` constructor in `ethtool_stats_linux.go` to include `gstring` and `stats` parameters, and updated the `EthtoolReader` struct to store these buffers. [[1]](diffhunk://#diff-5af3df7bd20ddc8cff54f839bbe143b959d17b3dbabf03ebb641b757bda3e53dR23-R33) [[2]](diffhunk://#diff-5af3df7bd20ddc8cff54f839bbe143b959d17b3dbabf03ebb641b757bda3e53dR49-R50) * Updated the `readInterfaceStats` method in `ethtool_stats_linux.go` to use the new `StatsWithBuffer` method. * Adjusted the `linuxUtil` plugin's `run` method in `linuxutil_linux.go` to create and pass `gstring` and `stats` buffers when initializing `EthtoolReader`. [[1]](diffhunk://#diff-b6f651749c3bf6ea907b4c65d0586b88fcd556b2debfccde42bc5e7f0300546cR72-R76) [[2]](diffhunk://#diff-b6f651749c3bf6ea907b4c65d0586b88fcd556b2debfccde42bc5e7f0300546cL112-R117) ### Test Updates: * Updated test cases in `ethtool_stats_linux_test.go` to accommodate the new `StatsWithBuffer` method and added mock objects for `gstring` and `stats` buffers. [[1]](diffhunk://#diff-9c5fe736fcf6bf9c090bf151701d8c765d0308c50a3091f23f9b7442bd712046R42-R46) [[2]](diffhunk://#diff-9c5fe736fcf6bf9c090bf151701d8c765d0308c50a3091f23f9b7442bd712046L59-R63) [[3]](diffhunk://#diff-9c5fe736fcf6bf9c090bf151701d8c765d0308c50a3091f23f9b7442bd712046R134-R138) [[4]](diffhunk://#diff-9c5fe736fcf6bf9c090bf151701d8c765d0308c50a3091f23f9b7442bd712046L138-R151) ### Mock Interface Changes: * Updated the mock implementation in `linuxutil_mock_generated_linux.go` to reflect the changes in `EthtoolInterface`, replacing `Stats` with `StatsWithBuffer`. These changes enhance the functionality and flexibility of the `EthtoolInterface` implementation, allowing for more efficient handling of interface statistics. ## Related Issue This will reduce the overall memory churn, leading to lower chances of memory spill. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Memory profile with this fix compared to with previous fix. ![image](https://github.com/user-attachments/assets/5265b2d5-985f-415a-9652-fbed3a77f485) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Ritwik Ranjan --- pkg/plugin/linuxutil/ethtool_handle_linux.go | 5 ++-- pkg/plugin/linuxutil/ethtool_stats_linux.go | 26 +++++++++++++++++-- .../linuxutil/ethtool_stats_linux_test.go | 17 +++++++++--- pkg/plugin/linuxutil/linuxutil_linux.go | 5 +++- .../linuxutil_mock_generated_linux.go | 13 +++++----- pkg/plugin/linuxutil/types_linux.go | 4 ++- 6 files changed, 54 insertions(+), 16 deletions(-) diff --git a/pkg/plugin/linuxutil/ethtool_handle_linux.go b/pkg/plugin/linuxutil/ethtool_handle_linux.go index ee71a8611f..42e7378a48 100644 --- a/pkg/plugin/linuxutil/ethtool_handle_linux.go +++ b/pkg/plugin/linuxutil/ethtool_handle_linux.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/pkg/errors" + "github.com/safchain/ethtool" lru "github.com/hashicorp/golang-lru/v2" @@ -26,13 +27,13 @@ func NewCachedEthtool(ethHandle EthtoolInterface, unsupportedInterfacesCache *lr var errskip = errors.New("skip interface") -func (ce *CachedEthtool) Stats(intf string) (map[string]uint64, error) { +func (ce *CachedEthtool) StatsWithBuffer(intf string, gstring *ethtool.EthtoolGStrings, stats *ethtool.EthtoolStats) (map[string]uint64, error) { // Skip unsupported interfaces if _, ok := ce.unsupported.Get(intf); ok { return nil, errskip } - ifaceStats, err := ce.EthtoolInterface.Stats(intf) + ifaceStats, err := ce.EthtoolInterface.StatsWithBuffer(intf, gstring, stats) if err != nil { if strings.Contains(err.Error(), "operation not supported") { ce.unsupported.Add(intf, struct{}{}) diff --git a/pkg/plugin/linuxutil/ethtool_stats_linux.go b/pkg/plugin/linuxutil/ethtool_stats_linux.go index 0d2088d846..2609bee969 100644 --- a/pkg/plugin/linuxutil/ethtool_stats_linux.go +++ b/pkg/plugin/linuxutil/ethtool_stats_linux.go @@ -20,9 +20,19 @@ type EthtoolReader struct { opts *EthtoolOpts data *EthtoolStats ethHandle EthtoolInterface + gstrings *ethtool.EthtoolGStrings + stats *ethtool.EthtoolStats } -func NewEthtoolReader(opts *EthtoolOpts, ethHandle EthtoolInterface, unsupportedInterfacesCache *lru.Cache[string, struct{}]) *EthtoolReader { +// if gstrings and stats are nil, a new buffer is initialized +// to avoid null pointer +func NewEthtoolReader( + opts *EthtoolOpts, + ethHandle EthtoolInterface, + unsupportedInterfacesCache *lru.Cache[string, struct{}], + gstrings *ethtool.EthtoolGStrings, + stats *ethtool.EthtoolStats, +) *EthtoolReader { if ethHandle == nil { var err error ethHandle, err = ethtool.NewEthtool() @@ -33,11 +43,23 @@ func NewEthtoolReader(opts *EthtoolOpts, ethHandle EthtoolInterface, unsupported } // Construct a cached ethtool handle CachedEthHandle := NewCachedEthtool(ethHandle, unsupportedInterfacesCache) + + // if gstrings is nil, initialize it + if gstrings == nil { + gstrings = ðtool.EthtoolGStrings{} + } + // if stats is nil, initialize it + if stats == nil { + stats = ðtool.EthtoolStats{} + } + return &EthtoolReader{ l: log.Logger().Named(string("EthtoolReader")), opts: opts, data: &EthtoolStats{}, ethHandle: CachedEthHandle, + gstrings: gstrings, + stats: stats, } } @@ -73,7 +95,7 @@ func (er *EthtoolReader) readInterfaceStats() error { } // Retrieve tx from eth0 - ifaceStats, err := er.ethHandle.Stats(i.Name) + ifaceStats, err := er.ethHandle.StatsWithBuffer(i.Name, er.gstrings, er.stats) if err != nil { if errors.Is(err, errskip) { er.l.Debug("Skipping unsupported interface", zap.String("ifacename", i.Name)) diff --git a/pkg/plugin/linuxutil/ethtool_stats_linux_test.go b/pkg/plugin/linuxutil/ethtool_stats_linux_test.go index d77044be32..563ebb0e82 100644 --- a/pkg/plugin/linuxutil/ethtool_stats_linux_test.go +++ b/pkg/plugin/linuxutil/ethtool_stats_linux_test.go @@ -5,6 +5,7 @@ import ( "testing" lru "github.com/hashicorp/golang-lru/v2" + "github.com/safchain/ethtool" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/metrics" @@ -38,8 +39,11 @@ func TestNewEthtool(t *testing.T) { t.Fatal("failed to create cache:", err) } + stats := new(ethtool.EthtoolStats) + gstrings := new(ethtool.EthtoolGStrings) + ethHandle := NewMockEthtoolInterface(ctrl) - ethReader := NewEthtoolReader(opts, ethHandle, unsupportedInterfacesCache) + ethReader := NewEthtoolReader(opts, ethHandle, unsupportedInterfacesCache, gstrings, stats) assert.NotNil(t, ethReader) } @@ -56,7 +60,7 @@ func TestNewEthtoolWithNil(t *testing.T) { t.Fatal("failed to create cache:", err) } - ethReader := NewEthtoolReader(opts, nil, unsupportedInterfacesCache) + ethReader := NewEthtoolReader(opts, nil, unsupportedInterfacesCache, nil, nil) assert.NotNil(t, ethReader) } @@ -127,6 +131,11 @@ func TestReadInterfaceStats(t *testing.T) { }, } + gstrings := new(ethtool.EthtoolGStrings) + stats := new(ethtool.EthtoolStats) + + // Create a mock EthtoolInterface + for _, tt := range tests { l.Infof("Running TestReadInterfaceStats %s", tt.name) @@ -135,11 +144,11 @@ func TestReadInterfaceStats(t *testing.T) { ethHandle := NewMockEthtoolInterface(ctrl) - ethReader := NewEthtoolReader(tt.opts, ethHandle, unsupportedInterfacesCache) + ethReader := NewEthtoolReader(tt.opts, ethHandle, unsupportedInterfacesCache, gstrings, stats) assert.NotNil(t, ethReader) - ethHandle.EXPECT().Stats(gomock.Any()).Return(tt.statsReturn, tt.statErr).AnyTimes() + ethHandle.EXPECT().StatsWithBuffer(gomock.Any(), gstrings, stats).Return(tt.statsReturn, tt.statErr).AnyTimes() InitalizeMetricsForTesting(ctrl) if tt.statErr == nil { diff --git a/pkg/plugin/linuxutil/linuxutil_linux.go b/pkg/plugin/linuxutil/linuxutil_linux.go index b96f6c698b..a6647ae8dd 100644 --- a/pkg/plugin/linuxutil/linuxutil_linux.go +++ b/pkg/plugin/linuxutil/linuxutil_linux.go @@ -69,6 +69,9 @@ func (lu *linuxUtil) run(ctx context.Context) error { return err } + gstrings := new(ethtool.EthtoolGStrings) + stats := new(ethtool.EthtoolStats) + ticker := time.NewTicker(lu.cfg.MetricsInterval) defer ticker.Stop() @@ -109,7 +112,7 @@ func (lu *linuxUtil) run(ctx context.Context) error { return fmt.Errorf("failed to create ethHandle: %w", err) } - ethReader := NewEthtoolReader(ethtoolOpts, ethHandle, unsupportedInterfacesCache) + ethReader := NewEthtoolReader(ethtoolOpts, ethHandle, unsupportedInterfacesCache, gstrings, stats) if ethReader == nil { lu.l.Error("Error while creating ethReader") return errors.New("error while creating ethReader") diff --git a/pkg/plugin/linuxutil/linuxutil_mock_generated_linux.go b/pkg/plugin/linuxutil/linuxutil_mock_generated_linux.go index c635ee37e9..dd35032ecb 100644 --- a/pkg/plugin/linuxutil/linuxutil_mock_generated_linux.go +++ b/pkg/plugin/linuxutil/linuxutil_mock_generated_linux.go @@ -13,6 +13,7 @@ import ( reflect "reflect" netstat "github.com/cakturk/go-netstat/netstat" + ethtool "github.com/safchain/ethtool" gomock "go.uber.org/mock/gomock" ) @@ -51,19 +52,19 @@ func (mr *MockEthtoolInterfaceMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockEthtoolInterface)(nil).Close)) } -// Stats mocks base method. -func (m *MockEthtoolInterface) Stats(intf string) (map[string]uint64, error) { +// StatsWithBuffer mocks base method. +func (m *MockEthtoolInterface) StatsWithBuffer(intf string, gstrings *ethtool.EthtoolGStrings, stats *ethtool.EthtoolStats) (map[string]uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Stats", intf) + ret := m.ctrl.Call(m, "StatsWithBuffer", intf, gstrings, stats) ret0, _ := ret[0].(map[string]uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// Stats indicates an expected call of Stats. -func (mr *MockEthtoolInterfaceMockRecorder) Stats(intf any) *gomock.Call { +// StatsWithBuffer indicates an expected call of StatsWithBuffer. +func (mr *MockEthtoolInterfaceMockRecorder) StatsWithBuffer(intf, gstrings, stats any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stats", reflect.TypeOf((*MockEthtoolInterface)(nil).Stats), intf) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatsWithBuffer", reflect.TypeOf((*MockEthtoolInterface)(nil).StatsWithBuffer), intf, gstrings, stats) } // MockNetstatInterface is a mock of NetstatInterface interface. diff --git a/pkg/plugin/linuxutil/types_linux.go b/pkg/plugin/linuxutil/types_linux.go index e7c20764fc..35f94d7328 100644 --- a/pkg/plugin/linuxutil/types_linux.go +++ b/pkg/plugin/linuxutil/types_linux.go @@ -6,6 +6,7 @@ import ( "github.com/cakturk/go-netstat/netstat" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" + "github.com/safchain/ethtool" ) const name = "linuxutil" @@ -106,7 +107,8 @@ type EthtoolOpts struct { } type EthtoolInterface interface { - Stats(intf string) (map[string]uint64, error) + // the buffer is used internally by the ethtool package to avoid memory allocation churn + StatsWithBuffer(intf string, gstrings *ethtool.EthtoolGStrings, stats *ethtool.EthtoolStats) (map[string]uint64, error) Close() } From 8e41f1bbde18c0e90a81937c5191fe90ad952108 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Sat, 7 Jun 2025 04:53:21 +0100 Subject: [PATCH 038/448] feat(capture download): Add ability to download capture files based on capture name (#1564) # Description This PR introduces the ability to download captures via the Retina CLI. It extends the `retina capture download` cmd to be able to download captures based on the capture name / blobURL. This enables the *manual* download of captures which occur *after* this PR. - This is because in order to make retrospective downloads possible, the download pods are now annotated with some metadata. Captures prior to this PR won't have this metadata, and it won't be possible to download them. Change list: - Update `retina capture list` to be more readable. - Change BlobURL download to be a flag `--blobUrl` rather than an ENV variable. - This makes it more consistent with the rest of the CLI. - Add annotations to capture pods to store metadata about the capture. - Download capture file from host node by passing name of capture which created the file. - By default, creates a folder in the current directory based on the name of the capture, which will contain the tarball. - Can set the output directory. (-o) - Example: `retina capture download --name download-me -o /tmp/retina/` - Add an E2E test for `retina capture create` ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots ### Examples and flags documentation ![{50A67E84-9D0C-49ED-997B-1C594C2C646E}](https://github.com/user-attachments/assets/7673b1be-42a7-423e-a672-669d607a7178) ### `k retina capture list` After ![{447597F0-3512-4F12-96C2-09DB0D66A210}](https://github.com/user-attachments/assets/8e507e7a-7c60-471c-8f74-e53bf77b71de) Before ![{83B47868-B31C-4A7D-8FDF-2F3BEFDAB1F9}](https://github.com/user-attachments/assets/99383fe6-f03e-4f8d-afc2-5cafdda1e592) ### Downloading a capture based on the capture name ![{3CC49A7E-9A7D-45C4-B7E0-C9DCB092B1C0}](https://github.com/user-attachments/assets/2e5c4495-95f4-4a6c-aebe-88fb1177c8d9) ![{C3B0F8E1-5037-4EDC-9E07-A6530A621B05}](https://github.com/user-attachments/assets/26112f77-86fa-492f-b18d-f946c474352f) ### E2E Retina Capture Create ![{90CB2A2D-409D-4F8F-A29D-1461862299EE}](https://github.com/user-attachments/assets/ccf195a7-7d75-40c5-8aa4-3e09d57a94e2) --------- Signed-off-by: Kamil Signed-off-by: Alex Castilio dos Santos Co-authored-by: Alex Castilio dos Santos --- cli/cmd/capture/create.go | 8 + cli/cmd/capture/download.go | 397 ++++++++++++++++-- cli/cmd/capture/table_util.go | 39 +- docs/04-Captures/02-cli.md | 43 +- pkg/capture/capture_manager.go | 5 +- pkg/capture/capture_manager_test.go | 2 +- pkg/capture/constants/annotations.go | 11 + pkg/capture/constants/job_env.go | 4 + pkg/capture/crd_to_job.go | 44 +- pkg/capture/crd_to_job_test.go | 2 +- pkg/capture/file/capture_filename.go | 6 +- pkg/capture/file/timestamp.go | 23 +- pkg/capture/provider/network_capture_test.go | 7 +- pkg/capture/provider/network_capture_unix.go | 3 +- pkg/capture/provider/network_capture_win.go | 3 +- pkg/capture/utils/annotations.go | 21 + test/e2e/jobs/jobs.go | 11 + test/e2e/retina_e2e_test.go | 8 + .../capture/install-retina-plugin.go | 107 +++++ test/e2e/scenarios/capture/scenarios.go | 29 ++ .../e2e/scenarios/capture/validate-capture.go | 272 ++++++++++++ 21 files changed, 939 insertions(+), 106 deletions(-) create mode 100644 pkg/capture/constants/annotations.go create mode 100644 pkg/capture/utils/annotations.go create mode 100644 test/e2e/scenarios/capture/install-retina-plugin.go create mode 100644 test/e2e/scenarios/capture/scenarios.go create mode 100644 test/e2e/scenarios/capture/validate-capture.go diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index 16b0f61fb0..ecd06174f9 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -28,6 +28,7 @@ import ( "github.com/microsoft/retina/internal/buildinfo" pkgcapture "github.com/microsoft/retina/pkg/capture" captureConstants "github.com/microsoft/retina/pkg/capture/constants" + "github.com/microsoft/retina/pkg/capture/file" captureUtils "github.com/microsoft/retina/pkg/capture/utils" "github.com/microsoft/retina/pkg/config" ) @@ -240,6 +241,8 @@ func deleteSecret(ctx context.Context, kubeClient kubernetes.Interface, secretNa } func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, error) { + timestamp := file.Now() + capture := &retinav1alpha1.Capture{ ObjectMeta: metav1.ObjectMeta{ Name: *opts.Name, @@ -253,8 +256,13 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti CaptureOption: retinav1alpha1.CaptureOption{}, }, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, } + retinacmd.Logger.Info(fmt.Sprintf("Capture timestamp: %s", timestamp)) + if duration != 0 { retinacmd.Logger.Info(fmt.Sprintf("The capture duration is set to %s", duration)) capture.Spec.CaptureConfiguration.CaptureOption.Duration = &metav1.Duration{Duration: duration} diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index c5add7ec85..f6957fa27d 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -4,82 +4,409 @@ package capture import ( + "bytes" + "context" "fmt" "io" "net/url" "os" + "os/signal" + "path/filepath" "strings" + "syscall" + "time" "github.com/Azure/azure-sdk-for-go/storage" + retinacmd "github.com/microsoft/retina/cli/cmd" + captureConstants "github.com/microsoft/retina/pkg/capture/constants" + captureLabels "github.com/microsoft/retina/pkg/label" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/remotecommand" + "k8s.io/kubectl/pkg/scheme" + "k8s.io/kubectl/pkg/util/i18n" + "k8s.io/kubectl/pkg/util/templates" ) -const BlobURL = "BLOB_URL" +const ( + DefaultOutputPath = "./" +) + +var ( + blobURL string + captureName string + outputPath string +) + +var ( + ErrNoPodFound = errors.New("no pod found for job") + ErrManyPodsFound = errors.New("more than one pod found for job; expected exactly one") + ErrCaptureContainerNotFound = errors.New("capture container not found in pod") + ErrFileNotAccessible = errors.New("file does not exist or is not readable") + ErrEmptyDownloadOutput = errors.New("download command produced no output") + ErrFailedToCreateDownloadPod = errors.New("failed to create download pod") +) + +var downloadExample = templates.Examples(i18n.T(` + # List Retina capture jobs + kubectl retina capture list -var ErrEmptyBlobURL = errors.Errorf("%s environment variable is empty. It must be set/exported", BlobURL) + # Download the capture file(s) created using the capture name + kubectl retina capture download --name + + # Download the capture file(s) created using the capture name and define output location + kubectl retina capture download --name -o + + # Download capture file(s) from Blob Storage via Blob URL (Blob URL requires Read/List permissions) + kubectl retina capture download --blob-url "" +`)) var downloadCapture = &cobra.Command{ - Use: "download", - Short: "Download Retina Captures", + Use: "download", + Short: "Download Retina Captures", + Example: downloadExample, RunE: func(*cobra.Command, []string) error { viper.AutomaticEnv() - blobURL := viper.GetString(BlobURL) - if blobURL == "" { - return ErrEmptyBlobURL + + kubeConfig, err := opts.ToRESTConfig() + if err != nil { + return errors.Wrap(err, "failed to compose k8s rest config") + } + + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) + defer cancel() + + captureNamespace := *opts.Namespace + if captureNamespace == "" { + captureNamespace = "default" + } + + if captureName == "" && blobURL == "" { + return errors.New("either --name or --blob-url must be specified") + } + + if captureName != "" { + err = downloadFromCluster(ctx, kubeConfig, captureNamespace) + if err != nil { + return err + } + } + + if blobURL != "" { + err = downloadFromBlob() + if err != nil { + return err + } + } + + return nil + }, +} + +func downloadFromCluster(ctx context.Context, config *rest.Config, namespace string) error { + kubeClient, err := kubernetes.NewForConfig(config) + if err != nil { + return errors.Wrap(err, "failed to initialize k8s client") + } + + pods, err := getCapturePods(ctx, kubeClient, captureName, namespace) + if err != nil { + return errors.Wrap(err, "failed to obtain capture pod") + } + + err = os.MkdirAll(filepath.Join(outputPath, captureName), 0o775) + if err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + + for i := range pods.Items { + pod := pods.Items[i] + if pod.Status.Phase != corev1.PodSucceeded { + return errors.Wrap(ErrNoPodFound, captureName) + } + + nodeName := pod.Spec.NodeName + hostPath, ok := pod.Annotations[captureConstants.CaptureHostPathAnnotationKey] + if !ok { + return errors.New("cannot obtain host path from pod annotations") + } + fileName, ok := pod.Annotations[captureConstants.CaptureFilenameAnnotationKey] + if !ok { + return errors.New("cannot obtain capture file name from pod annotations") } - u, err := url.Parse(blobURL) + srcFilePath := "/" + filepath.Join("host", hostPath, fileName) + ".tar.gz" + fmt.Println("\nFile to be downloaded: ", srcFilePath) + downloadPod, err := createDownloadPod(ctx, kubeClient, namespace, nodeName, hostPath, captureName) if err != nil { - return errors.Wrapf(err, "failed to parse SAS URL %s", blobURL) + return err } - // blobService, err := storage.NewAccountSASClientFromEndpointToken(u.String(), u.Query().Encode()).GetBlobService() - b, err := storage.NewAccountSASClientFromEndpointToken(u.String(), u.Query().Encode()) + fmt.Println("Obtaining file...") + exec, err := createDownloadExec(ctx, kubeClient, config, downloadPod, srcFilePath) if err != nil { - return errors.Wrap(err, "failed to create storage account client") + return err + } + + var outBuf, errBuf bytes.Buffer + streamOpts := remotecommand.StreamOptions{ + Stdout: &outBuf, + Stderr: &errBuf, + } + if err = exec.StreamWithContext(ctx, streamOpts); err != nil { + return fmt.Errorf("failed to exec in download container: %w", err) } - blobService := b.GetBlobService() - containerPath := strings.TrimLeft(u.Path, "/") - splitPath := strings.SplitN(containerPath, "/", 2) //nolint:gomnd // TODO string splitting probably isn't the right way to parse this URL? - containerName := splitPath[0] + if outBuf.Len() == 0 { + return errors.Wrap(ErrEmptyDownloadOutput, errBuf.String()) + } - params := storage.ListBlobsParameters{Prefix: *opts.Name} - blobList, err := blobService.GetContainerReference(containerName).ListBlobs(params) + outputFile := filepath.Join(outputPath, captureName, fileName+".tar.gz") + fmt.Printf("Bytes retrieved: %d\n", outBuf.Len()) + + err = os.WriteFile(outputFile, outBuf.Bytes(), 0o600) if err != nil { - return errors.Wrap(err, "failed to list blobstore ") + return fmt.Errorf("failed to write file to host: %w", err) } - if len(blobList.Blobs) == 0 { - return errors.Errorf("no blobs found with prefix: %s", *opts.Name) + fmt.Println("File written to: ", outputFile) + + err = kubeClient.CoreV1().Pods(namespace).Delete(ctx, downloadPod.Name, metav1.DeleteOptions{}) + if err != nil { + retinacmd.Logger.Warn("Failed to clean up debug pod", zap.String("name", downloadPod.Name), zap.Error(err)) } + } + + return nil +} - for _, v := range blobList.Blobs { - blob := blobService.GetContainerReference(containerName).GetBlobReference(v.Name) - readCloser, err := blob.Get(&storage.GetBlobOptions{}) +func getCapturePods(ctx context.Context, kubeClient *kubernetes.Clientset, captureName, namespace string) (*corev1.PodList, error) { + pods, err := kubeClient.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{ + LabelSelector: captureLabels.CaptureNameLabel + "=" + captureName, + }) + if err != nil { + return &corev1.PodList{}, fmt.Errorf("failed to obtain list of pods: %w", err) + } + if len(pods.Items) == 0 { + return &corev1.PodList{}, errors.Wrap(ErrNoPodFound, captureName) + } + + return pods, nil +} + +func createDownloadPod(ctx context.Context, kubeClient *kubernetes.Clientset, namespace, nodeName, hostPath, captureName string) (*corev1.Pod, error) { + podName := captureName + "-download-" + rand.String(5) + + podSpec := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: namespace, + }, + Spec: corev1.PodSpec{ + NodeName: nodeName, + Containers: []corev1.Container{ + { + Name: "download", + Image: "busybox", + Command: []string{"sh", "-c", "echo 'Download pod ready'; sleep 3600"}, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "host-mount", + MountPath: "/" + filepath.Join("host", hostPath), + }, + }, + }, + }, + RestartPolicy: corev1.RestartPolicyNever, + Volumes: []corev1.Volume{ + { + Name: "host-mount", + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: hostPath, + }, + }, + }, + }, + }, + } + + fmt.Printf("Creating download pod: %s\n", podName) + _, err := kubeClient.CoreV1().Pods(namespace).Create(ctx, podSpec, metav1.CreateOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to create download pod: %w", err) + } + + timeout := time.After(30 * time.Second) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + var pod *corev1.Pod + for { + select { + case <-timeout: + return nil, errors.Wrap(ErrFailedToCreateDownloadPod, "timeout waiting for download pod to become ready") + case <-ticker.C: + pod, err = kubeClient.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{}) if err != nil { - return errors.Wrap(err, "failed to read from blobstore") + return nil, fmt.Errorf("failed to get download pod: %w", err) } + if pod.Status.Phase == corev1.PodRunning { + return pod, nil + } + if pod.Status.Phase == corev1.PodFailed { + return nil, errors.Wrap(ErrFailedToCreateDownloadPod, "download pod failed to spin up successfully") + } + } + } +} - defer readCloser.Close() +func verifyFileExists(ctx context.Context, kubeClient *kubernetes.Clientset, config *rest.Config, pod *corev1.Pod, filePath string) (bool, error) { + maxAttempts := 3 - blobData, err := io.ReadAll(readCloser) - if err != nil { - return errors.Wrap(err, "failed to obtain blob from blobstore") + for attempt := 1; attempt <= maxAttempts; attempt++ { + checkReq := kubeClient.CoreV1().RESTClient().Post(). + Resource("pods"). + Name(pod.Name). + Namespace(pod.Namespace). + SubResource("exec"). + VersionedParams(&corev1.PodExecOptions{ + Container: "download", + Command: []string{"sh", "-c", fmt.Sprintf("if [ -r %q ]; then echo 'FILE_EXISTS'; fi", filePath)}, + Stdout: true, + Stderr: true, + }, scheme.ParameterCodec) + + checkExec, err := remotecommand.NewSPDYExecutor(config, "POST", checkReq.URL()) + if err != nil { + if attempt == maxAttempts { + return false, fmt.Errorf("failed to create check executor after %d attempts: %w", attempt, err) } + time.Sleep(time.Duration(attempt*2) * time.Second) + continue + } - err = os.WriteFile(v.Name, blobData, 0o644) //nolint:gosec,gomnd // intentionally permissive bitmask - if err != nil { - return errors.Wrap(err, "failed to write file") + var checkBuf bytes.Buffer + if err = checkExec.StreamWithContext(ctx, remotecommand.StreamOptions{ + Stdout: &checkBuf, + Stderr: &checkBuf, + }); err != nil { + if attempt == maxAttempts { + return false, fmt.Errorf("failed to check file existence after %d attempts: %w", attempt, err) } - fmt.Println("Downloaded blob: ", v.Name) + time.Sleep(time.Duration(attempt*2) * time.Second) + continue } - return nil - }, + + checkOutput := checkBuf.String() + + if strings.Contains(checkOutput, "FILE_EXISTS") { + return true, nil + } + + time.Sleep(time.Duration(attempt*2) * time.Second) + } + + return false, errors.Wrap(ErrFileNotAccessible, filePath) +} + +func createDownloadExec(ctx context.Context, kubeClient *kubernetes.Clientset, config *rest.Config, pod *corev1.Pod, srcFilePath string) (remotecommand.Executor, error) { + fileExists, err := verifyFileExists(ctx, kubeClient, config, pod, srcFilePath) + if err != nil || !fileExists { + return nil, err + } + + req := kubeClient.CoreV1().RESTClient().Post(). + Resource("pods"). + Name(pod.Name). + Namespace(pod.Namespace). + SubResource("exec"). + VersionedParams(&corev1.PodExecOptions{ + Container: "download", + Command: []string{"cat", srcFilePath}, + Stdout: true, + Stderr: true, + }, scheme.ParameterCodec) + + exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL()) + if err != nil { + return nil, fmt.Errorf("failed to create executor: %w", err) + } + return exec, nil +} + +func downloadFromBlob() error { + u, err := url.Parse(blobURL) + if err != nil { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Wrapf(err, "failed to parse SAS URL %s", blobURL) + } + + b, err := storage.NewAccountSASClientFromEndpointToken(u.String(), u.Query().Encode()) + if err != nil { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Wrap(err, "failed to create storage account client") + } + + blobService := b.GetBlobService() + containerPath := strings.TrimLeft(u.Path, "/") + splitPath := strings.SplitN(containerPath, "/", 2) + containerName := splitPath[0] + + params := storage.ListBlobsParameters{Prefix: *opts.Name} + blobList, err := blobService.GetContainerReference(containerName).ListBlobs(params) + if err != nil { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Wrap(err, "failed to list blobstore ") + } + + if len(blobList.Blobs) == 0 { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Errorf("no blobs found with prefix: %s", *opts.Name) + } + + err = os.MkdirAll(outputPath, 0o775) + if err != nil { + return fmt.Errorf("failed to create output directory: %w", err) + } + + for i := range blobList.Blobs { + blob := blobList.Blobs[i] + blobRef := blobService.GetContainerReference(containerName).GetBlobReference(blob.Name) + readCloser, err := blobRef.Get(&storage.GetBlobOptions{}) + if err != nil { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Wrap(err, "failed to read from blobstore") + } + + blobData, err := io.ReadAll(readCloser) + readCloser.Close() + if err != nil { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Wrap(err, "failed to obtain blob from blobstore") + } + + outputFile := filepath.Join(outputPath, blob.Name) + err = os.WriteFile(outputFile, blobData, 0o600) + if err != nil { + retinacmd.Logger.Error("err: ", zap.Error(err)) + return errors.Wrap(err, "failed to write file") + } + + fmt.Println("Downloaded: ", outputFile) + } + return nil } func init() { capture.AddCommand(downloadCapture) + downloadCapture.Flags().StringVar(&blobURL, "blob-url", "", "Blob URL from which to download") + downloadCapture.Flags().StringVar(&captureName, "name", "", "The name of a the capture") + downloadCapture.Flags().StringVarP(&outputPath, "output", "o", DefaultOutputPath, "Path to save the downloaded capture") } diff --git a/cli/cmd/capture/table_util.go b/cli/cmd/capture/table_util.go index 3f3c5389a4..4d81fb8e93 100644 --- a/cli/cmd/capture/table_util.go +++ b/cli/cmd/capture/table_util.go @@ -74,32 +74,23 @@ func printCaptureResult(captureJobs []batchv1.Job) { w := new(tabwriter.Writer) w.Init(os.Stdout, 0, 8, 3, ' ', 0) - fmt.Fprintln(w, "NAMESPACE\tCAPTURE NAME\tJOBS\tCOMPLETIONS\tAGE") - for captureRef, jobs := range captureToJobs { - captureRef := strings.Split(captureRef, "/") - captureNamespace, captureName := captureRef[0], captureRef[1] - jobNames := []string{} - completedJobNum := 0 - age := "" - totalJobNum := len(jobs) - for _, job := range jobs { - jobNames = append(jobNames, job.Name) - if job.Status.CompletionTime != nil { - completedJobNum += 1 - } - } - sort.SliceStable(jobNames, func(i, j int) bool { - return jobNames[i] < jobNames[j] - }) - if len(jobs) > 0 { - age = durationUtil.HumanDuration(time.Since(jobs[0].CreationTimestamp.Time)) - } + fmt.Fprintln(w, "NAMESPACE\tCAPTURE NAME\tJOB\tCOMPLETIONS\tAGE") - jobsNameJoined := strings.Join(jobNames, ",") + for captureRef := range captureToJobs { + jobs := captureToJobs[captureRef] + captureParts := strings.Split(captureRef, "/") + captureNamespace, captureName := captureParts[0], captureParts[1] - completions := fmt.Sprintf("%d/%d", completedJobNum, totalJobNum) - rr := fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t", captureNamespace, captureName, jobsNameJoined, completions, age) - fmt.Fprintln(w, rr) + sort.SliceStable(jobs, func(i, j int) bool { + return jobs[i].Name < jobs[j].Name + }) + + for i := range jobs { + job := &jobs[i] + completions := fmt.Sprintf("%d/%d", job.Status.Succeeded, *job.Spec.Completions) + age := durationUtil.HumanDuration(time.Since(job.CreationTimestamp.Time)) + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", captureNamespace, captureName, job.Name, completions, age) + } } w.Flush() fmt.Println() diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index 50d97c9008..4bb02ae2f5 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -205,6 +205,47 @@ List by all namespaces: kubectl retina capture list --all-namespaces ``` +### Capture Download + +The `kubectl retina capture download` command allows you to download capture files directly from the cluster or from blob storage. + +#### Download from Cluster + +Download capture files using the capture name: + +```sh +kubectl retina capture download --name +``` + +Download capture files and specify an output location: + +```sh +kubectl retina capture download --name -o +``` + +By default, files are downloaded to the current directory. + +#### Download from Blob Storage + +Download capture files from Azure Blob Storage using a Blob URL (requires Read/List permissions): + +```sh +kubectl retina capture download --blob-url "" +``` + +#### Download Output Structure + +The command will create a directory with the capture name and download all related capture files. Each capture file is downloaded as a `.tar.gz` archive with a name pattern matching `$(capturename)-$(hostname)-$(date +%Y%m%d%H%M%S%Z).tar.gz`. + +For example: + +```bash +/output-directory/ +└── capture-name/ + ├── capture-name-node1-20230320013600UTC.tar.gz + └── capture-name-node2-20230320013600UTC.tar.gz +``` + ## Obtaining the output After downloading or copying the tarball from the location specified, extract the tarball through the `tar` command in either Linux shell or Windows Powershell, for example, @@ -317,7 +358,7 @@ kubectl retina capture create \ --host-path /mnt/test \ --namespace capture \ --node-selectors "kubernetes.io/os=linux" \ - -- + --debug ``` ## Cleanup diff --git a/pkg/capture/capture_manager.go b/pkg/capture/capture_manager.go index c953a9746e..c0e5550386 100644 --- a/pkg/capture/capture_manager.go +++ b/pkg/capture/capture_manager.go @@ -24,6 +24,7 @@ import ( "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/telemetry" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // CaptureManager captures network packets and metadata into tar ball, then send the tar ball to the location(s) @@ -105,8 +106,8 @@ func (cm *CaptureManager) captureNodeHostName() string { return os.Getenv(captureConstants.NodeHostNameEnvKey) } -func (cm *CaptureManager) captureStartTimestamp() (*file.Timestamp, error) { - timestamp, err := file.StringToTimestamp((os.Getenv(captureConstants.CaptureStartTimestampEnvKey))) +func (cm *CaptureManager) captureStartTimestamp() (*metav1.Time, error) { + timestamp, err := file.StringToTime((os.Getenv(captureConstants.CaptureStartTimestampEnvKey))) if err != nil { return nil, errors.Wrap(err, "failed to parse timestamp") } diff --git a/pkg/capture/capture_manager_test.go b/pkg/capture/capture_manager_test.go index 3fc92fa01a..affa0e560c 100644 --- a/pkg/capture/capture_manager_test.go +++ b/pkg/capture/capture_manager_test.go @@ -53,7 +53,7 @@ func TestCaptureNetwork(t *testing.T) { ctx, cancel := TestContext(t) defer cancel() - tmpFilename := file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: ×tamp} + tmpFilename := file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} networkCaptureProvider.EXPECT().Setup(tmpFilename).Return(fmt.Sprintf("%s-%s-%s", captureName, nodeHostName, ×tamp), nil).Times(1) networkCaptureProvider.EXPECT().CaptureNetworkPacket(ctx, filter, duration, maxSize).Return(nil).Times(1) diff --git a/pkg/capture/constants/annotations.go b/pkg/capture/constants/annotations.go new file mode 100644 index 0000000000..8f28496b88 --- /dev/null +++ b/pkg/capture/constants/annotations.go @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package constants + +// Capture job specification +const ( + CaptureFilenameAnnotationKey string = "retina-capture-filename" + CaptureTimestampAnnotationKey string = "retina-capture-timestamp" + CaptureHostPathAnnotationKey string = "retina-capture-hostpath" +) diff --git a/pkg/capture/constants/job_env.go b/pkg/capture/constants/job_env.go index 1ec9a67cd1..cabc939872 100644 --- a/pkg/capture/constants/job_env.go +++ b/pkg/capture/constants/job_env.go @@ -20,6 +20,10 @@ const ( NodeHostNameEnvKey string = "NODE_HOST_NAME" CaptureStartTimestampEnvKey string = "CAPTURE_START_TIMESTAMP" + NamespaceEnvKey string = "NAMESPACE" + PodNameEnvKey string = "POD_NAME" + ContainerNameEnvKey string = "CONTAINER_NAME" + CaptureFilterEnvKey string = "CAPTURE_FILTER" CaptureDurationEnvKey string = "CAPTURE_DURATION" CaptureMaxSizeEnvKey string = "CAPTURE_MAX_SIZE" diff --git a/pkg/capture/crd_to_job.go b/pkg/capture/crd_to_job.go index 537b5563b9..358b972483 100644 --- a/pkg/capture/crd_to_job.go +++ b/pkg/capture/crd_to_job.go @@ -124,8 +124,9 @@ func (translator *CaptureToPodTranslator) initJobTemplate(ctx context.Context, c BackoffLimit: &backoffLimit, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: captureUtils.GetContainerLabelsFromCaptureName(capture.Name), - Namespace: capture.Namespace, + Labels: captureUtils.GetContainerLabelsFromCaptureName(capture.Name), + Namespace: capture.Namespace, + Annotations: captureUtils.GetPodAnnotationsFromCapture(capture), }, Spec: corev1.PodSpec{ HostNetwork: true, @@ -384,9 +385,15 @@ func (translator *CaptureToPodTranslator) renderJob(captureTargetOnNode *Capture return nil, fmt.Errorf("no nodes are selected") } - captureStartTimestamp := file.Now() + stringTimestamp := translator.jobTemplate.Spec.Template.ObjectMeta.Annotations[captureConstants.CaptureTimestampAnnotationKey] + captureTimestamp, err := file.StringToTime(stringTimestamp) + if err != nil { + return nil, fmt.Errorf("failed to parse capture start timestamp: %w", err) + } - printOutputFileNames(captureTargetOnNode, envCommon, &captureStartTimestamp) + fmt.Println("#########################") + fmt.Println("Expected Capture Files") + fmt.Println("#########################") jobs := make([]*batchv1.Job, 0, len(*captureTargetOnNode)) for nodeName, target := range *captureTargetOnNode { @@ -395,6 +402,14 @@ func (translator *CaptureToPodTranslator) renderJob(captureTargetOnNode *Capture jobEnv[k] = v } job := translator.jobTemplate.DeepCopy() + captureFilename := &file.CaptureFilename{ + CaptureName: envCommon[captureConstants.CaptureNameEnvKey], + NodeHostname: nodeName, + StartTimestamp: captureTimestamp, + } + job.Spec.Template.ObjectMeta.Annotations[captureConstants.CaptureFilenameAnnotationKey] = captureFilename.String() + + fmt.Printf("%s.tar.gz\n", captureFilename.String()) job.Spec.Template.Spec.Affinity = &corev1.Affinity{ NodeAffinity: &corev1.NodeAffinity{ @@ -454,30 +469,15 @@ func (translator *CaptureToPodTranslator) renderJob(captureTargetOnNode *Capture job.Spec.Template.Spec.Containers[0].Env = append(job.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: k, Value: v}) } job.Spec.Template.Spec.Containers[0].Env = append(job.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: captureConstants.NodeHostNameEnvKey, Value: nodeName}) - job.Spec.Template.Spec.Containers[0].Env = append(job.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: captureConstants.CaptureStartTimestampEnvKey, Value: captureStartTimestamp.String()}) + job.Spec.Template.Spec.Containers[0].Env = append(job.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: captureConstants.CaptureStartTimestampEnvKey, Value: stringTimestamp}) jobs = append(jobs, job) } - return jobs, nil -} - -func printOutputFileNames(captureTargetOnNode *CaptureTargetsOnNode, envCommon map[string]string, timestamp *file.Timestamp) { - captureFileNames := []string{} - for k := range *captureTargetOnNode { - capture := file.CaptureFilename{CaptureName: envCommon[captureConstants.CaptureNameEnvKey], NodeHostname: k, StartTimestamp: timestamp} - captureFileNames = append(captureFileNames, capture.String()) - } - fmt.Println("#########################") - fmt.Println("Expected Capture Files") - fmt.Println("#########################") - - for _, v := range captureFileNames { - fmt.Printf("%s.tar.gz\n", v) - } - fmt.Println("\nNote: The file(s) may not be created if the capture job(s) fail prematurely.") fmt.Println("#########################") + + return jobs, nil } func updateTcpdumpFilterWithPodIPAddress(podIPAddresses []string, tcpdumpFilter string) string { diff --git a/pkg/capture/crd_to_job_test.go b/pkg/capture/crd_to_job_test.go index 4113ee0be1..19c49f1be5 100644 --- a/pkg/capture/crd_to_job_test.go +++ b/pkg/capture/crd_to_job_test.go @@ -1737,7 +1737,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { for _, env := range tt.podEnv { if env.Name == captureConstants.CaptureStartTimestampEnvKey { - _, err := file.StringToTimestamp(env.Value) + _, err := file.StringToTime(env.Value) if err != nil { t.Errorf("TranslateCaptureToJobs() error with capture timestamp: %v", err) } diff --git a/pkg/capture/file/capture_filename.go b/pkg/capture/file/capture_filename.go index 70f2bf2eb8..e308eba940 100644 --- a/pkg/capture/file/capture_filename.go +++ b/pkg/capture/file/capture_filename.go @@ -2,15 +2,17 @@ package file import ( "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type CaptureFilename struct { CaptureName string NodeHostname string - StartTimestamp *Timestamp + StartTimestamp *metav1.Time } func (cf *CaptureFilename) String() string { - uniqueName := fmt.Sprintf("%s-%s-%s", cf.CaptureName, cf.NodeHostname, cf.StartTimestamp) + uniqueName := fmt.Sprintf("%s-%s-%s", cf.CaptureName, cf.NodeHostname, TimeToString(cf.StartTimestamp)) return uniqueName } diff --git a/pkg/capture/file/timestamp.go b/pkg/capture/file/timestamp.go index d3725e71e2..553dcafc01 100644 --- a/pkg/capture/file/timestamp.go +++ b/pkg/capture/file/timestamp.go @@ -4,26 +4,25 @@ import ( "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -type Timestamp struct { - time.Time -} - const captureFileNameTimestampFormat string = "20060102150405UTC" -func Now() Timestamp { - return Timestamp{Time: time.Now().UTC().Truncate(time.Second)} -} - -func (timestamp *Timestamp) String() string { - return timestamp.Time.Format(captureFileNameTimestampFormat) +func Now() *metav1.Time { + return &metav1.Time{Time: time.Now().UTC().Truncate(time.Second)} } -func StringToTimestamp(timestamp string) (*Timestamp, error) { +// Converts a string in the capture file name format to metav1.Time +func StringToTime(timestamp string) (*metav1.Time, error) { parsedTime, err := time.Parse(captureFileNameTimestampFormat, timestamp) if err != nil { return nil, errors.Wrap(err, "failed to create timestamp from string") } - return &Timestamp{parsedTime}, nil + return &metav1.Time{Time: parsedTime}, nil +} + +// Converts a metav1.Time to a string in the capture file name format +func TimeToString(timestamp *metav1.Time) string { + return timestamp.Format(captureFileNameTimestampFormat) } diff --git a/pkg/capture/provider/network_capture_test.go b/pkg/capture/provider/network_capture_test.go index 5a715af59c..b81893239e 100644 --- a/pkg/capture/provider/network_capture_test.go +++ b/pkg/capture/provider/network_capture_test.go @@ -7,7 +7,6 @@ import ( "os" "strings" "testing" - "time" "github.com/microsoft/retina/pkg/capture/file" "github.com/microsoft/retina/pkg/log" @@ -16,10 +15,10 @@ import ( func TestSetupAndCleanup(t *testing.T) { captureName := "capture-test" nodeHostName := "node1" - timestamp := file.Timestamp{Time: time.Now().UTC()} + timestamp := file.Now() log.SetupZapLogger(log.GetDefaultLogOpts()) networkCaptureprovider := &NetworkCaptureProvider{l: log.Logger().Named("test")} - tmpFilename := file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: ×tamp} + tmpFilename := file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} tmpCaptureLocation, err := networkCaptureprovider.Setup(tmpFilename) // remove temporary capture dir anyway in case Cleanup() fails. @@ -34,7 +33,7 @@ func TestSetupAndCleanup(t *testing.T) { if !strings.Contains(tmpCaptureLocation, nodeHostName) { t.Errorf("Temporary capture dir name %s should contains node host name %s", tmpCaptureLocation, nodeHostName) } - if !strings.Contains(tmpCaptureLocation, timestamp.String()) { + if !strings.Contains(tmpCaptureLocation, file.TimeToString(timestamp)) { t.Errorf("Temporary capture dir name %s should contain timestamp %s", tmpCaptureLocation, timestamp) } diff --git a/pkg/capture/provider/network_capture_unix.go b/pkg/capture/provider/network_capture_unix.go index 0288964539..5027d50b42 100644 --- a/pkg/capture/provider/network_capture_unix.go +++ b/pkg/capture/provider/network_capture_unix.go @@ -20,6 +20,7 @@ import ( captureConstants "github.com/microsoft/retina/pkg/capture/constants" "github.com/microsoft/retina/pkg/capture/file" "github.com/microsoft/retina/pkg/log" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type NetworkCaptureProvider struct { @@ -27,7 +28,7 @@ type NetworkCaptureProvider struct { TmpCaptureDir string CaptureName string NodeHostName string - StartTimestamp *file.Timestamp + StartTimestamp *metav1.Time l *log.ZapLogger } diff --git a/pkg/capture/provider/network_capture_win.go b/pkg/capture/provider/network_capture_win.go index a15da1c746..57a5e7e930 100644 --- a/pkg/capture/provider/network_capture_win.go +++ b/pkg/capture/provider/network_capture_win.go @@ -18,6 +18,7 @@ import ( "time" "go.uber.org/zap" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" captureConstants "github.com/microsoft/retina/pkg/capture/constants" "github.com/microsoft/retina/pkg/capture/file" @@ -29,7 +30,7 @@ type NetworkCaptureProvider struct { TmpCaptureDir string CaptureName string NodeHostName string - StartTimestamp *file.Timestamp + StartTimestamp *metav1.Time Filename file.CaptureFilename l *log.ZapLogger diff --git a/pkg/capture/utils/annotations.go b/pkg/capture/utils/annotations.go new file mode 100644 index 0000000000..afb4fee8ce --- /dev/null +++ b/pkg/capture/utils/annotations.go @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package utils + +import ( + retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" + captureConstants "github.com/microsoft/retina/pkg/capture/constants" + "github.com/microsoft/retina/pkg/capture/file" +) + +func GetPodAnnotationsFromCapture(capture *retinav1alpha1.Capture) map[string]string { + annotations := map[string]string{ + captureConstants.CaptureFilenameAnnotationKey: capture.Name, + captureConstants.CaptureTimestampAnnotationKey: file.TimeToString(capture.Status.StartTime), + } + if capture.Spec.OutputConfiguration.HostPath != nil { + annotations[captureConstants.CaptureHostPathAnnotationKey] = *capture.Spec.OutputConfiguration.HostPath + } + return annotations +} diff --git a/test/e2e/jobs/jobs.go b/test/e2e/jobs/jobs.go index f08ad80737..5ce624fc11 100644 --- a/test/e2e/jobs/jobs.go +++ b/test/e2e/jobs/jobs.go @@ -7,6 +7,7 @@ import ( "github.com/microsoft/retina/test/e2e/framework/kubernetes" "github.com/microsoft/retina/test/e2e/framework/types" "github.com/microsoft/retina/test/e2e/hubble" + "github.com/microsoft/retina/test/e2e/scenarios/capture" "github.com/microsoft/retina/test/e2e/scenarios/dns" "github.com/microsoft/retina/test/e2e/scenarios/drop" "github.com/microsoft/retina/test/e2e/scenarios/latency" @@ -267,6 +268,16 @@ func ValidateHubble(kubeConfigFilePath, chartPath string, testPodNamespace strin return job } +func ValidateCapture(kubeConfigFilePath, testPodNamespace string) *types.Job { + job := types.NewJob("Validate Capture") + + job.AddScenario(capture.ValidateCapture( + kubeConfigFilePath, + testPodNamespace)) + + return job +} + func LoadGenericFlags() *types.Job { job := types.NewJob("Loading Generic Flags to env") diff --git a/test/e2e/retina_e2e_test.go b/test/e2e/retina_e2e_test.go index 9cf7c58315..33f19a72f4 100644 --- a/test/e2e/retina_e2e_test.go +++ b/test/e2e/retina_e2e_test.go @@ -62,4 +62,12 @@ func TestE2ERetina(t *testing.T) { common.TestPodNamespace), ) validatehubble.Run(ctx) + + // Install Retina basic and test captures + captureE2E := types.NewRunner(t, + jobs.ValidateCapture( + common.KubeConfigFilePath(rootDir), + "default"), + ) + captureE2E.Run(ctx) } diff --git a/test/e2e/scenarios/capture/install-retina-plugin.go b/test/e2e/scenarios/capture/install-retina-plugin.go new file mode 100644 index 0000000000..8ac6dc54c0 --- /dev/null +++ b/test/e2e/scenarios/capture/install-retina-plugin.go @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +package capture + +import ( + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/pkg/errors" +) + +const ( + // InstallRetinaBinaryDir is the directory where the kubectl-retina binary will be installed + InstallRetinaBinaryDir = "/tmp/retina-bin" +) + +// InstallRetinaPlugin builds and installs the kubectl-retina plugin +// to allow e2e tests to run kubectl retina commands. +type InstallRetinaPlugin struct{} + +// Run builds the kubectl-retina binary and adds it to PATH +func (i *InstallRetinaPlugin) Run() error { + log.Print("Building kubectl-retina plugin...") + + // Create binary directory if it doesn't exist + if err := os.MkdirAll(InstallRetinaBinaryDir, 0o755); err != nil { + return errors.Wrap(err, "failed to create binary directory") + } + + binaryName := "kubectl-retina" + + // Run git rev-parse to find the repository root + cmd := exec.Command("git", "rev-parse", "--show-toplevel") // #nosec + output, err := cmd.Output() + if err != nil { + return errors.Wrap(err, "failed to detect git repository root. Make sure you're running inside a git repository") + } + retinaRepoRoot := strings.TrimSpace(string(output)) + log.Printf("Auto-detected repository root: %s", retinaRepoRoot) + + _, err = os.Stat(retinaRepoRoot) + if err != nil { + return errors.Wrap(err, "invalid RetinaRepoRoot path") + } + + // Check if the cli/main.go file exists + _, err = os.Stat(filepath.Join(retinaRepoRoot, "cli", "main.go")) + if err != nil { + return errors.Wrap(err, "cli/main.go not found in repository root") + } + + // Build the kubectl-retina binary + buildCmd := exec.Command("go", "build", "-o", + filepath.Join(InstallRetinaBinaryDir, binaryName), + filepath.Join(retinaRepoRoot, "cli", "main.go")) // #nosec + + buildCmd.Dir = retinaRepoRoot + var buildOutput []byte + buildOutput, err = buildCmd.CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to build kubectl-retina: %s", buildOutput) + } + log.Printf("Successfully built kubectl-retina: %s", buildOutput) + + // Add the binary directory to PATH + currentPath := os.Getenv("PATH") + + // Check if the directory is already in PATH + if !strings.Contains(currentPath, InstallRetinaBinaryDir) { + newPath := fmt.Sprintf("%s:%s", InstallRetinaBinaryDir, currentPath) + err = os.Setenv("PATH", newPath) + if err != nil { + return errors.Wrap(err, "failed to update PATH environment variable") + } + log.Printf("Added %s to PATH", InstallRetinaBinaryDir) + } + + // Verify the plugin is accessible via kubectl + verifyCmd := exec.Command("kubectl", "plugin", "list") // #nosec + verifyOutput, err := verifyCmd.CombinedOutput() + if err != nil { + log.Printf("Warning: kubectl plugin list command failed: %v. Output: %s", err, verifyOutput) + } else { + log.Printf("kubectl plugin list output: %s", verifyOutput) + if !strings.Contains(string(verifyOutput), "retina") { + log.Printf("Warning: retina plugin not found in kubectl plugin list output") + } + } + + return nil +} + +// Prevalidate validates the inputs before running +func (i *InstallRetinaPlugin) Prevalidate() error { + // Check if the repository root exists + + return nil +} + +// Stop is a no-op for this step +func (i *InstallRetinaPlugin) Stop() error { + return nil +} diff --git a/test/e2e/scenarios/capture/scenarios.go b/test/e2e/scenarios/capture/scenarios.go new file mode 100644 index 0000000000..fcda5ebfa1 --- /dev/null +++ b/test/e2e/scenarios/capture/scenarios.go @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +package capture + +import ( + "github.com/microsoft/retina/test/e2e/framework/types" + "k8s.io/apimachinery/pkg/util/rand" +) + +func ValidateCapture(kubeConfigPath, namespace string) *types.Scenario { + scenarioName := "Retina Capture" + captureName := "retina-capture-e2e-" + rand.String(5) + steps := []*types.StepWrapper{ + { + Step: &InstallRetinaPlugin{}, + }, + { + Step: &validateCapture{ + CaptureName: captureName, + CaptureNamespace: namespace, + Duration: "5s", + KubeConfigPath: kubeConfigPath, + }, Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + } + return types.NewScenario(scenarioName, steps...) +} diff --git a/test/e2e/scenarios/capture/validate-capture.go b/test/e2e/scenarios/capture/validate-capture.go new file mode 100644 index 0000000000..047e6e70ce --- /dev/null +++ b/test/e2e/scenarios/capture/validate-capture.go @@ -0,0 +1,272 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +package capture + +import ( + "context" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + + captureConstants "github.com/microsoft/retina/pkg/capture/constants" + "github.com/microsoft/retina/pkg/label" + "github.com/microsoft/retina/test/e2e/framework/generic" + "github.com/microsoft/retina/test/retry" +) + +type validateCapture struct { + CaptureName string + CaptureNamespace string + Duration string + KubeConfigPath string +} + +var ( + ErrInvalidCaptureName = errors.New("invalid capture name") + ErrNoCaptureJobsFound = errors.New("no capture jobs found") + ErrFoundNonZeroCaptureJobs = errors.New("found non-zero amount of capture jobs when expecting zero after deletion") + ErrMissingEventOnCaptureJob = errors.New("missing SuccessfulCreate or Completed event on capture job") + ErrCaptureJobFailed = errors.New("capture job failed") +) + +func (v *validateCapture) Run() error { + log.Print("Running retina capture create...") + ctx := context.TODO() + + imageRegistry := os.Getenv(generic.DefaultImageRegistry) + imageNamespace := os.Getenv(generic.DefaultImageNamespace) + imageTag := os.Getenv(generic.DefaultTagEnv) + + cmd := exec.CommandContext(ctx, "kubectl", "retina", "capture", "create", "--namespace", v.CaptureNamespace, "--name", v.CaptureName, "--duration", v.Duration, "--debug") //#nosec + cmd.Env = append(os.Environ(), "RETINA_AGENT_IMAGE="+filepath.Join(imageRegistry, imageNamespace, "retina-agent:"+imageTag)) + + output, err := cmd.CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to execute create capture command") + } + log.Printf("Create capture command output: %s\n", output) + + config, err := clientcmd.BuildConfigFromFlags("", v.KubeConfigPath) + if err != nil { + return errors.Wrap(err, "failed to build kubeconfig") + } + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return errors.Wrap(err, "failed to create kubernetes clientset") + } + + retrier := retry.Retrier{Attempts: 5, Delay: 10 * time.Second, ExpBackoff: true} + err = retrier.Do(ctx, func() error { + e := v.verifyJobs(ctx, clientset) + if e != nil { + log.Printf("failed to verify capture jobs: %v, retrying...", e) + return e + } + return nil + }) + if err != nil { + return errors.Wrap(err, "failed to verify capture jobs were created") + } + + err = v.downloadCapture(ctx) + if err != nil { + return errors.Wrap(err, "failed to download and validate capture files") + } + + err = v.deleteJobs(ctx, clientset) + if err != nil { + return errors.Wrap(err, "failed to delete capture jobs") + } + + return nil +} + +// Verify that capture jobs are created (with appropriate labels), and completed successfully +func (v *validateCapture) verifyJobs(ctx context.Context, clientset *kubernetes.Clientset) error { + captureJobSelector := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + label.CaptureNameLabel: v.CaptureName, + label.AppLabel: captureConstants.CaptureAppname, + }, + } + labelSelector, err := labels.Parse(metav1.FormatLabelSelector(captureJobSelector)) + if err != nil { + return errors.Wrap(err, "failed to parse label selector") + } + + jobList, err := clientset.BatchV1().Jobs(v.CaptureNamespace).List(ctx, metav1.ListOptions{ + LabelSelector: labelSelector.String(), + }) + if err != nil { + return errors.Wrap(err, "failed to list capture jobs") + } + + if len(jobList.Items) == 0 { + return errors.Wrap(ErrNoCaptureJobsFound, fmt.Sprintf("with labels %s=%s and %s=%s", + label.CaptureNameLabel, v.CaptureName, + label.AppLabel, captureConstants.CaptureAppname)) + } + + log.Printf("Found %d capture job(s) with appropriate labels.", len(jobList.Items)) + + // Check if all jobs are completed successfully + for i := range jobList.Items { + for _, condition := range jobList.Items[i].Status.Conditions { + if condition.Type == "Complete" && condition.Status == "True" { + log.Printf("Job %s has condition: Complete - True", jobList.Items[i].Name) + } + if condition.Type == "Failed" && condition.Status == "True" { + return errors.Wrap(ErrCaptureJobFailed, jobList.Items[i].Name) + } + } + } + + // Check events for each job to verify SuccessfulCreate and Completed + events, err := clientset.CoreV1().Events(v.CaptureNamespace).List(ctx, metav1.ListOptions{}) + if err != nil { + return fmt.Errorf("failed to list events: %w", err) + } + for i := range jobList.Items { + if err = v.checkJobEvents(jobList.Items[i].Name, events); err != nil { + return fmt.Errorf("failed to verify events for job %s: %w", jobList.Items[i].Name, err) + } + log.Printf("Job %s has both SuccessfulCreate and Completed events.", jobList.Items[i].Name) + } + + return nil +} + +func (v *validateCapture) deleteJobs(ctx context.Context, clientset *kubernetes.Clientset) error { + log.Printf("Running retina capture delete...") + cmd := exec.CommandContext(ctx, "kubectl", "retina", "capture", "delete", "--namespace", v.CaptureNamespace, "--name", v.CaptureName) //#nosec + output, err := cmd.CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to execute delete command") + } + log.Printf("Delete command output: %s\n", output) + + captureJobSelector := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + label.CaptureNameLabel: v.CaptureName, + label.AppLabel: captureConstants.CaptureAppname, + }, + } + labelSelector, err := labels.Parse(metav1.FormatLabelSelector(captureJobSelector)) + if err != nil { + return errors.Wrap(err, "failed to parse label selector") + } + // Verify that jobs are deleted + if err := v.verifyDelete(ctx, clientset, labelSelector); err != nil { + return errors.Wrap(err, "failed to verify capture jobs were deleted") + } + + return nil +} + +func (v *validateCapture) checkJobEvents(jobName string, events *v1.EventList) error { + var created, completed bool + for i := range events.Items { + if events.Items[i].InvolvedObject.Kind == "Job" && events.Items[i].InvolvedObject.Name == jobName { + switch events.Items[i].Reason { + case "SuccessfulCreate": + created = true + case "Completed": + completed = true + } + } + } + + if !created || !completed { + return errors.Wrap(ErrMissingEventOnCaptureJob, jobName) + } + + return nil +} + +func (v *validateCapture) verifyDelete(ctx context.Context, clientset *kubernetes.Clientset, labelSelector labels.Selector) error { + // Wait a moment for deletion to propagate + time.Sleep(5 * time.Second) + + jobList, err := clientset.BatchV1().Jobs(v.CaptureNamespace).List(ctx, metav1.ListOptions{ + LabelSelector: labelSelector.String(), + }) + if err != nil { + return errors.Wrap(err, "failed to list jobs during delete verification") + } + + if len(jobList.Items) > 0 { + return ErrFoundNonZeroCaptureJobs + } + + log.Printf("All relevant capture jobs have been successfully deleted.") + return nil +} + +func (v *validateCapture) Prevalidate() error { + return nil +} + +func (v *validateCapture) Stop() error { + return nil +} + +func (v *validateCapture) downloadCapture(ctx context.Context) error { + log.Print("Downloading capture files...") + + outputDir := filepath.Join(".", v.CaptureName) + + // Run the download command + cmd := exec.CommandContext(ctx, "kubectl", "retina", "capture", "download", "--namespace", v.CaptureNamespace, "--name", v.CaptureName) // #nosec + output, err := cmd.CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to execute download capture command: %s", string(output)) + } + log.Printf("Download capture command output: %s\n", output) + + // List files in the output directory + files, err := os.ReadDir(outputDir) + if err != nil { + return errors.Wrapf(err, "failed to list files in output directory %s", outputDir) + } + + // Validate the number of files + if len(files) == 0 { + return errors.New("no capture files were downloaded") + } + log.Printf("Downloaded %d capture files", len(files)) + + // Validate file names and content + for _, file := range files { + filePath := filepath.Join(outputDir, file.Name()) + + // Check that the file has the expected tar.gz extension + if !strings.HasSuffix(file.Name(), ".tar.gz") { + return errors.Errorf("downloaded file %s does not have the expected .tar.gz extension", file.Name()) + } + + // Check that the file is not empty + fileInfo, err := os.Stat(filePath) + if err != nil { + return errors.Wrapf(err, "failed to get file info for %s", filePath) + } + + if fileInfo.Size() == 0 { + return errors.Errorf("downloaded file %s is empty", filePath) + } + + log.Printf("Validated file: %s (Size: %d bytes)", file.Name(), fileInfo.Size()) + } + + return nil +} From 7b1942cd637f3bd5ad1050c25d58e389d31cc91b Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Mon, 9 Jun 2025 15:30:16 +0100 Subject: [PATCH 039/448] fix: exclude aznfs package from installed packages list (#1667) # Description Retina Shell Image Build is failing due to failure to install `aznfs` package which is a new dependency of `conntrack` package added recently for some reason. Previous successful pipeline execution did not show that in the list of packages being installed: https://github.com/microsoft/retina/actions/runs/15496126524/job/43634783255 First failed pipeline execution with the problem: https://github.com/microsoft/retina/actions/runs/15530534142/job/43721335257 This PR adds `--exclude=aznfs` to the `tdnf install` command in the `shell/Dockerfile` to exclude the `aznfs` package from the list of installed packages as a workaround. There's an issue created about it in azurelinux repository: https://github.com/microsoft/azurelinux/issues/13971 References below: ![image](https://github.com/user-attachments/assets/a720ee9e-37fb-4706-8d73-42799a5a1427) ![image](https://github.com/user-attachments/assets/c29fac43-e5ff-4100-b300-b955091087a3) ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- shell/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/Dockerfile b/shell/Dockerfile index 797d624049..241c26790b 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -23,6 +23,7 @@ RUN tdnf install -y \ socat \ tcpdump \ wget \ + --exclude=aznfs \ && tdnf clean all CMD ["/bin/bash", "-l"] From e5ef53f5214310556ada434642c1eb3be13f8f6a Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 11 Jun 2025 10:48:27 +0100 Subject: [PATCH 040/448] test: fix e2e test for retina capture (#1666) # Description PR https://github.com/microsoft/retina/pull/1564 was merged with e2e failed execution for retina capture. This PR fixes the e2e test for retina capture by adding the `KUBECONFIG` environment variable to run the `kubectl` command correctly. Commits: * improve output of e2e test for retina capture create in case of error * Add `KUBECONFIG` env variable to run `kubectl` command correctly Link to successful e2e test execution for retina capture (only e2e for retina capture was tested in the following run): https://github.com/microsoft/retina/actions/runs/15539842820/job/43748366816 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos --- test/e2e/scenarios/capture/validate-capture.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/e2e/scenarios/capture/validate-capture.go b/test/e2e/scenarios/capture/validate-capture.go index 047e6e70ce..62aec20c1e 100644 --- a/test/e2e/scenarios/capture/validate-capture.go +++ b/test/e2e/scenarios/capture/validate-capture.go @@ -48,12 +48,15 @@ func (v *validateCapture) Run() error { imageNamespace := os.Getenv(generic.DefaultImageNamespace) imageTag := os.Getenv(generic.DefaultTagEnv) + os.Setenv("KUBECONFIG", v.KubeConfigPath) + log.Printf("KUBECONFIG: %s\n", os.Getenv("KUBECONFIG")) + cmd := exec.CommandContext(ctx, "kubectl", "retina", "capture", "create", "--namespace", v.CaptureNamespace, "--name", v.CaptureName, "--duration", v.Duration, "--debug") //#nosec cmd.Env = append(os.Environ(), "RETINA_AGENT_IMAGE="+filepath.Join(imageRegistry, imageNamespace, "retina-agent:"+imageTag)) output, err := cmd.CombinedOutput() if err != nil { - return errors.Wrapf(err, "failed to execute create capture command") + return errors.Wrapf(err, "failed to execute create capture command: %s", string(output)) } log.Printf("Create capture command output: %s\n", output) From 044c8045deb4467350b38c98d100ee4302050e3a Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 11 Jun 2025 13:35:33 +0100 Subject: [PATCH 041/448] fix: revert: exclude aznfs package from installed packages list (#1675) Reverts microsoft/retina#1667 It was a workaround for an issue that was fixed: https://github.com/microsoft/azurelinux/issues/13971#issuecomment-2956384627 --- shell/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/Dockerfile b/shell/Dockerfile index 241c26790b..797d624049 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -23,7 +23,6 @@ RUN tdnf install -y \ socat \ tcpdump \ wget \ - --exclude=aznfs \ && tdnf clean all CMD ["/bin/bash", "-l"] From b76bbcdb0ede6665d75755eaf0d8fd0ae07edfd0 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:05:10 +0100 Subject: [PATCH 042/448] chore(shell): Add pwru binary to retina-shell (#1664) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Add eBPF-based [pwru](https://github.com/cilium/pwru) executable binary to retina-shell for tracing network packets in the Linux kernel with advanced filtering capabilities ## Related Issue #1662 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed I have tested by building the image in isolation ```sh docker buildx build \ --platform linux/amd64,linux/arm64 \ --build-arg GOARCH=amd64 \ -t ghcr.io/srodi/retina/retina-shell \ --push . ``` And run on both linux/amd64 and linux/arm64 ```sh ❯ docker run --rm -it ghcr.io/srodi/retina/retina-shell \ pwru --version Unable to find image 'ghcr.io/srodi/retina/retina-shell:latest' locally latest: Pulling from srodi/retina/retina-shell 67f02795c36b: Pull complete 879a565e8972: Pull complete b825e06ce1fe: Pull complete Digest: sha256:24877a745d4fa6f0ab5b5cb17399e13b8b764961658be53676e8749cb2f7525c Status: Downloaded newer image for ghcr.io/srodi/retina/retina-shell:latest pwru v1.0.9 ``` test `pwru` run with no caps ```sh ❯ docker run --rm -it ghcr.io/srodi/retina/retina-shell pwru 2025/06/06 09:34:10 Failed to set temporary rlimit: failed to set memlock rlimit: operation not permitted ``` test with CAPS ```sh ❯ docker run --rm -it \ --cap-add=NET_ADMIN \ --cap-add=SYS_ADMIN \ ghcr.io/srodi/retina/retina-shell pwru 2025/06/06 09:34:46 Attaching kprobes (via kprobe)... 917 / 1616 [-------------------------------------------------------------------------------------->_________________________________________________________________] 56.75% 483 p/s1102 / 1616 [------------------------------------------------------------------------------------------------------>________________________________________________] 68.19% 507 p/s 2025/06/06 09:34:48 Listening for events.. SKB CPU PROCESS NETNS MARK/x IFACE PROTO MTU LEN TUPLE FUNC 0xffff9d258a213ee8 0 :4017 4026532313 0 1 0x0800 65536 309 172.18.0.2:6443->172.18.0.2:39754(tcp) 0xffffffff8bdb2754 ``` Test `node debugging` on AKS ![image](https://github.com/user-attachments/assets/26065ad2-6c3b-4380-b60e-059f26b0e077) Test `pod debugging` on AKS ![image](https://github.com/user-attachments/assets/e15a966a-1fce-49fe-bcbe-0d1d1a05eadf) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- Makefile | 2 +- shell/Dockerfile | 24 ++++++++++++++++++++++++ shell/README.md | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 80ccaf3b37..8ae30dabc3 100644 --- a/Makefile +++ b/Makefile @@ -412,7 +412,7 @@ manifests: cd crd && make manifests && make generate # Fetch the latest tag from the GitHub -LATEST_TAG := $(shell curl -s https://api.github.com/repos/microsoft/retina/releases | jq -r '.[0].name') +LATEST_TAG := $(shell curl -s https://api.github.com/repos/microsoft/retina/releases/latest | jq -r '.name') HELM_IMAGE_TAG ?= $(LATEST_TAG) diff --git a/shell/Dockerfile b/shell/Dockerfile index 797d624049..896eb5b0b8 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -23,6 +23,30 @@ RUN tdnf install -y \ socat \ tcpdump \ wget \ + tar \ + file \ && tdnf clean all +# Re-use existing arg from Makefile target "container-docker" +# https://github.com/microsoft/retina/blob/main/Makefile#L224 +ARG GOARCH=amd64 +ENV ARCH=${GOARCH} +# https://github.com/cilium/pwru/releases +ARG PWRU_TAG="v1.0.9" +ENV PWRU_TAG=${PWRU_TAG} + +# Download and extract latest pwru release for the correct architecture (amd64 or arm64) +RUN set -eux; \ + case "$ARCH" in \ + amd64|x86_64) PWRU_ARCH="amd64" ;; \ + arm64|aarch64) PWRU_ARCH="arm64" ;; \ + *) echo "Unsupported arch: $ARCH" && exit 1 ;; \ + esac; \ + PWRU_TAR="pwru-linux-${PWRU_ARCH}.tar.gz"; \ + curl -fL -o /tmp/pwru.tar.gz "https://github.com/cilium/pwru/releases/download/${PWRU_TAG}/${PWRU_TAR}"; \ + tar -xz -C /usr/local/bin -f /tmp/pwru.tar.gz pwru; \ + chmod +x /usr/local/bin/pwru; \ + rm /tmp/pwru.tar.gz; \ + file /usr/local/bin/pwru | grep -q 'ELF' + CMD ["/bin/bash", "-l"] diff --git a/shell/README.md b/shell/README.md index 1f3033814c..1013f8b8a2 100644 --- a/shell/README.md +++ b/shell/README.md @@ -4,6 +4,7 @@ Retina CLI provides a command to launch an interactive shell in a node or pod fo * The CLI command `kubectl retina shell` creates a pod with `HostNetwork=true` (for node debugging) or an ephemeral container in an existing pod (for pod debugging). * The container runs an image built from the Dockerfile in this directory. The image is based on Azure Linux and includes commonly-used networking tools. +* The [pwru](https://github.com/cilium/pwru) tool is bundled in the image for advanced kernel packet tracing. For testing, you can override the image used by `retina shell` either with CLI arguments (`--retina-shell-image-repo` and `--retina-shell-image-version`) or environment variables @@ -11,4 +12,26 @@ For testing, you can override the image used by `retina shell` either with CLI a Run `kubectl retina shell -h` for full documentation and examples. +## Example: Running pwru + +To use `pwru` inside the retina shell, you must grant the following Linux capabilities to the container: + +* `NET_ADMIN` +* `SYS_ADMIN` + +Capability requirements are based on common eBPF tool practices and not directly from the pwru documentation. + +Example command to launch a shell with the required capabilities: + +```sh +# Pod debugging +kubectl retina shell -n kube-system pod/coredns-57d886c994-8m2ph --capabilities=NET_ADMIN,SYS_ADMIN +``` + +Once inside the shell, you can run: + +```sh +pwru --help +``` + Currently only Linux is supported; Windows support will be added in the future. From b6265544fa31f2426388bd7eaf4d8a6d57b7368b Mon Sep 17 00:00:00 2001 From: Vamsi Kalapala Date: Thu, 12 Jun 2025 14:23:01 -0700 Subject: [PATCH 043/448] feat: add a script to watch for drops (#1671) # Description This PR introduces a comprehensive script, designed to monitor network packet drop counters in Kubernetes clusters. It automates the detection of either Retina or Cilium network monitoring agents, retrieves relevant metrics, and presents a clear, actionable summary of changes over time. ## Usage : The name of the Kubernetes node to monitor. [interval]: The polling interval in seconds (default: 30). --debug: Enables debug output. ## Technical Details Agent Detection: Uses kubectl to identify Retina or Cilium pods based on labels. Metrics Retrieval: Employs curl to fetch metrics from agent and Hubble endpoints. Change Analysis: Compares metrics using associative arrays and awk for numeric calculations. Port Forwarding: Leverages kubectl port-forward to access metrics endpoints. ## Dependencies kubectl curl grep sort lsof (optional) image --------- Signed-off-by: Vamsi Kalapala --- scripts/watch_drops.sh | 752 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 752 insertions(+) create mode 100755 scripts/watch_drops.sh diff --git a/scripts/watch_drops.sh b/scripts/watch_drops.sh new file mode 100755 index 0000000000..8512ba51c4 --- /dev/null +++ b/scripts/watch_drops.sh @@ -0,0 +1,752 @@ +#!/usr/bin/env bash +set -o pipefail + +############################################################################### +# HELP & ARGUMENT PARSING +############################################################################### +usage() { + cat <&2 +} + +# Set initial DEBUG flag for early usage +DEBUG=0 +for arg in "$@"; do + [[ "$arg" == "--debug" ]] && DEBUG=1 && break +done + +# Function to detect agent type automatically +detect_agent_type() { + debug "Detecting agent type in cluster..." + + # Check for Retina pods first - try k8s-app=retina (more common) + local retina_pods=$(kubectl get pods -n kube-system -l k8s-app=retina --no-headers 2>/dev/null | wc -l) + if [[ $retina_pods -gt 0 ]]; then + debug "Found $retina_pods Retina pods in cluster (k8s-app=retina)" + echo "retina" + return 0 + fi + + # Check for Retina pods with alternative label + local retina_alt_pods=$(kubectl get pods -n kube-system -l app=retina --no-headers 2>/dev/null | wc -l) + if [[ $retina_alt_pods -gt 0 ]]; then + debug "Found $retina_alt_pods Retina pods in cluster (app=retina)" + echo "retina" + return 0 + fi + + # Check for Cilium pods + local cilium_pods=$(kubectl get pods -n kube-system -l k8s-app=cilium --no-headers 2>/dev/null | wc -l) + if [[ $cilium_pods -gt 0 ]]; then + debug "Found $cilium_pods Cilium pods in cluster" + echo "cilium" + return 0 + fi + + # Check for alternative Cilium selectors + local cilium_alt_pods=$(kubectl get pods -n kube-system -l app=cilium --no-headers 2>/dev/null | wc -l) + if [[ $cilium_alt_pods -gt 0 ]]; then + debug "Found $cilium_alt_pods Cilium pods (with app=cilium selector) in cluster" + echo "cilium" + return 0 + fi + + # No supported agent found + echo "" + return 1 +} + +# Detect agent type automatically +echo "Detecting network monitoring agent in cluster..." +AGENT_TYPE=$(detect_agent_type) + +if [[ -z "$AGENT_TYPE" ]]; then + echo "Error: No supported network monitoring agent found in cluster" + echo "This script supports:" + echo " • Retina (pods with label app=retina)" + echo " • Cilium (pods with label k8s-app=cilium or app=cilium)" + echo "" + echo "Available pods in kube-system namespace:" + kubectl get pods -n kube-system --no-headers | head -20 + exit 1 +fi + +echo "Detected agent type: $AGENT_TYPE" + +# Configure agent-specific settings +if [[ "$AGENT_TYPE" == "retina" ]]; then + AGENT_PORT=10093 + AGENT_NS="kube-system" + AGENT_SELECTOR="k8s-app=retina" +elif [[ "$AGENT_TYPE" == "cilium" ]]; then + AGENT_PORT=9962 + AGENT_NS="kube-system" + # Use the more common selector first, fallback handled in get_agent_pod function + AGENT_SELECTOR="k8s-app=cilium" +else + echo "Error: Unsupported agent type detected: $AGENT_TYPE" + exit 1 +fi + +# Parse node name (now the first argument) +if [[ $# -eq 0 ]]; then + echo "Error: NODE name is required" + usage +fi +NODE="$1" +shift + +# Parse interval (optional) +INTERVAL=30 +if [[ $# -gt 0 && "$1" != "--debug" ]]; then + if [[ "$1" =~ ^[0-9]+$ ]]; then + INTERVAL="$1" + shift + else + echo "Error: INTERVAL must be a number" + usage + fi +fi + +# Parse debug flag (optional) +DEBUG=0 +if [[ $# -gt 0 && "$1" == "--debug" ]]; then + DEBUG=1 +fi + +############################################################################### +# FUNCTIONS +############################################################################### + +# Colorize text if supported +colorize() { + local text=$1 + local type=$2 # "good", "bad", or "neutral" + + # Check if we're in a terminal that supports colors + if [[ -t 1 && -n "$TERM" && "$TERM" != "dumb" ]]; then + if [[ "$type" == "good" ]]; then + echo -e "\033[32m$text\033[0m" # Green + elif [[ "$type" == "bad" ]]; then + echo -e "\033[31m$text\033[0m" # Red + elif [[ "$type" == "neutral" ]]; then + echo -e "\033[33m$text\033[0m" # Yellow + else + echo "$text" + fi + else + echo "$text" + fi +} + +# Get the pod name for the agent running on the specified node +get_agent_pod() { + local node=$1 + + debug "kubectl get pods -n $AGENT_NS -l $AGENT_SELECTOR --field-selector spec.nodeName=$node -o jsonpath='{.items[0].metadata.name}'" + + # First check if any pods match our criteria and output more detail if we have issues + local pod_count=$(kubectl get pods -n $AGENT_NS -l $AGENT_SELECTOR --field-selector spec.nodeName=$node -o name 2>/dev/null | wc -l) + + # If no pods found with primary selector, try alternative selectors + if [[ $pod_count -eq 0 && "$AGENT_TYPE" == "cilium" && "$AGENT_SELECTOR" == "k8s-app=cilium" ]]; then + debug "No pods found with k8s-app=cilium selector, trying app=cilium..." + AGENT_SELECTOR="app=cilium" + pod_count=$(kubectl get pods -n $AGENT_NS -l $AGENT_SELECTOR --field-selector spec.nodeName=$node -o name 2>/dev/null | wc -l) + elif [[ $pod_count -eq 0 && "$AGENT_TYPE" == "retina" && "$AGENT_SELECTOR" == "k8s-app=retina" ]]; then + debug "No pods found with k8s-app=retina selector, trying app=retina..." + AGENT_SELECTOR="app=retina" + pod_count=$(kubectl get pods -n $AGENT_NS -l $AGENT_SELECTOR --field-selector spec.nodeName=$node -o name 2>/dev/null | wc -l) + fi + + if [[ $pod_count -eq 0 ]]; then + echo "No pods found with selector '$AGENT_SELECTOR' on node '$node'" >&2 + echo "Available pods in namespace $AGENT_NS:" >&2 + kubectl get pods -n $AGENT_NS -o wide | grep $node >&2 || true + echo "Trying to find any retina or cilium pods on this node:" >&2 + kubectl get pods -n $AGENT_NS -o wide | grep -E "(retina|cilium)" | grep $node >&2 || true + return 1 + fi + + kubectl get pods -n $AGENT_NS -l $AGENT_SELECTOR --field-selector spec.nodeName=$node -o jsonpath='{.items[0].metadata.name}' +} + +# Setup port forwarding +setup_port_forward() { + local pod=$1 + local local_port=$2 + local remote_port=$3 + local pid_var=$4 + + debug "kubectl port-forward -n $AGENT_NS $pod $local_port:$remote_port &" + + # Check if the port is already in use + if lsof -i:$local_port &>/dev/null; then + echo "Port $local_port is already in use. Killing process..." + lsof -i:$local_port -t | xargs kill -9 2>/dev/null || true + sleep 1 + fi + + # Start port forwarding + kubectl port-forward -n $AGENT_NS "$pod" "$local_port:$remote_port" & + eval "$pid_var=$!" + + # Give port-forward a moment to establish + sleep 2 + + # Check if port-forward is still running + if ! kill -0 "${!pid_var}" 2>/dev/null; then + echo "Port-forward process ${!pid_var} failed to start or died immediately" + return 1 + fi + + # Verify the port is actually listening + if ! lsof -i:$local_port &>/dev/null; then + echo "Port $local_port is not listening after port-forward setup" + return 1 + fi + + return 0 +} + +# Get metrics from endpoint +get_metrics() { + local endpoint=$1 + + debug "curl -s -m 5 $endpoint" + local metrics + metrics=$(curl -s -m 5 "$endpoint" || echo "") + + if [[ $DEBUG -eq 1 && -n "$metrics" ]]; then + local filename="$(date +%Y%m%d-%H%M%S)-${endpoint##*/}-metrics.txt" + filename="${filename//\//_}" + echo "$metrics" > "$filename" + debug "Metrics saved to $filename" + fi + + echo "$metrics" +} + +# Extract drop counts from metrics +parse_drops() { + local metrics=$1 + local prefix=$2 + local alternative_patterns=${3:-""} # Optional additional patterns to search with default empty string + + if [[ -z "$metrics" ]]; then + return 0 + fi + + local drop_metrics="" + + # First try specific patterns based on the prefix + if [[ "$prefix" == "cilium" ]]; then + # For cilium, check multiple drop-related patterns + drop_metrics=$(echo "$metrics" | grep -E "(drop_count_total|drop_bytes_total|_dropped|_errors_total)" | sort) + elif [[ "$prefix" == "retina" ]]; then + # For retina, use its specific patterns - Retina uses different metric names + drop_metrics=$(echo "$metrics" | grep -E "(drop_count|dropped_packets|packet_drop|networkobservability.*drop)" | sort) + elif [[ "$prefix" == "hubble" ]]; then + # For hubble, use its specific patterns + drop_metrics=$(echo "$metrics" | grep -E "(hubble_drop_total|hubble.*drop|flow.*drop)" | sort) + else + # Generic fallback + drop_metrics=$(echo "$metrics" | grep -E "(drop|dropped)" | sort) + fi + + # If no metrics found with specific patterns, try generic drop patterns + if [[ -z "$drop_metrics" ]]; then + debug "No metrics found with $prefix patterns, trying generic drop patterns..." + drop_metrics=$(echo "$metrics" | grep -iE "(drop|dropped)" | grep -v " 0$" | sort) + fi + + # If alternative patterns were provided and no metrics found, try those + if [[ -z "$drop_metrics" && -n "$alternative_patterns" ]]; then + drop_metrics=$(echo "$metrics" | grep -E "$alternative_patterns" | sort) + fi + + if [[ -z "$drop_metrics" && $DEBUG -eq 1 ]]; then + echo "DEBUG: No drop metrics found with standard patterns for prefix '$prefix'" >&2 + echo "DEBUG: Trying generic 'drop' pattern..." >&2 + local generic_drops=$(echo "$metrics" | grep -i "drop" | head -5) + if [[ -n "$generic_drops" ]]; then + echo "DEBUG: Found some metrics containing 'drop':" >&2 + echo "$generic_drops" >&2 + else + echo "DEBUG: No metrics containing 'drop' found" >&2 + echo "DEBUG: Looking for error or packet metrics..." >&2 + echo "$metrics" | grep -i -E "(error|packet|reject)" | head -5 >&2 + fi + + # Create a debug file with all metrics for analysis + local debug_file="${prefix}_all_metrics.txt" + echo "$metrics" > "$debug_file" + echo "DEBUG: All metrics saved to $debug_file for analysis" >&2 + fi + + echo "$drop_metrics" +} + +# Cleanup function +cleanup() { + debug "Cleaning up port forwards" + [[ -n "${AGENT_PF_PID:-}" ]] && kill -9 $AGENT_PF_PID 2>/dev/null || true + [[ -n "${HUBBLE_PF_PID:-}" ]] && kill -9 $HUBBLE_PF_PID 2>/dev/null || true + exit 0 +} + +# Extract drop counts into a structured format +extract_structured_drops() { + local metrics=$1 + local agent_type=$2 + local output_file=$3 + + debug "Extracting structured drops for $agent_type to $output_file" + debug "Input metrics has $(echo "$metrics" | wc -l) lines" + + local line_count=0 + # Process each line of the metrics to a simpler format + while IFS= read -r line; do + # Skip comment and empty lines + [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue + + # Skip zero values if not in debug mode + [[ "$line" =~ [[:space:]]0$ && $DEBUG -eq 0 ]] && continue + + # Extract the key information and append to the output file + echo "$agent_type: $line" >> "$output_file" + line_count=$((line_count + 1)) + [[ $DEBUG -eq 1 ]] && debug "Added line: $agent_type: $line" + done <<< "$metrics" + + # Debug check file contents + debug "Wrote $line_count lines to $output_file" + if [[ $DEBUG -eq 1 && -f "$output_file" ]]; then + debug "File contents (first 10 lines):" + head -10 "$output_file" >&2 + fi +} + +# Create a comparison table from old and new metrics +generate_diff_table() { + local old_metrics_file=$1 + local new_metrics_file=$2 + local output_file=$3 + + debug "Generating diff table: comparing $old_metrics_file and $new_metrics_file" + + # Ensure output file is empty + > "$output_file" + + # Check if files exist and have content + if [[ ! -s "$old_metrics_file" ]]; then + debug "Warning: Old metrics file is empty or doesn't exist" + echo "No previous metrics data available for comparison" > "$output_file" + return 0 + fi + + if [[ ! -s "$new_metrics_file" ]]; then + debug "Warning: New metrics file is empty or doesn't exist" + echo "No current metrics data available for comparison" > "$output_file" + return 0 + fi + + # Create table header + echo "=== Drop Counter Changes ===" > "$output_file" + echo "" >> "$output_file" + printf "%-80s %15s %15s %15s\n" "Metric Name" "Previous" "Current" "Change" >> "$output_file" + printf "%-80s %15s %15s %15s\n" "$(printf '%*s' 80 '' | tr ' ' '-')" "$(printf '%*s' 15 '' | tr ' ' '-')" "$(printf '%*s' 15 '' | tr ' ' '-')" "$(printf '%*s' 15 '' | tr ' ' '-')" >> "$output_file" + + # Create associative arrays to store old and new values + declare -A old_values new_values + local changes_found=0 + + # Parse old metrics + while IFS= read -r line; do + if [[ -n "$line" && ! "$line" =~ ^# ]]; then + # Extract metric name and value + local metric_name=$(echo "$line" | sed 's/^[^:]*: //' | awk '{print $1}') + local metric_value=$(echo "$line" | awk '{print $NF}') + old_values["$metric_name"]="$metric_value" + fi + done < "$old_metrics_file" + + # Parse new metrics + while IFS= read -r line; do + if [[ -n "$line" && ! "$line" =~ ^# ]]; then + # Extract metric name and value + local metric_name=$(echo "$line" | sed 's/^[^:]*: //' | awk '{print $1}') + local metric_value=$(echo "$line" | awk '{print $NF}') + new_values["$metric_name"]="$metric_value" + fi + done < "$new_metrics_file" + + # Compare metrics and generate table rows + local all_metrics=() + + # Collect all unique metric names + for metric in "${!old_values[@]}"; do + all_metrics+=("$metric") + done + for metric in "${!new_values[@]}"; do + if [[ ! " ${all_metrics[*]} " =~ " ${metric} " ]]; then + all_metrics+=("$metric") + fi + done + + # Sort metrics for consistent output + IFS=$'\n' all_metrics=($(sort <<<"${all_metrics[*]}")) + unset IFS + + # Generate table rows + for metric in "${all_metrics[@]}"; do + local old_val="${old_values[$metric]:-0}" + local new_val="${new_values[$metric]:-0}" + + # Only show metrics that have changed or are non-zero + if [[ "$old_val" != "$new_val" ]] || [[ "$old_val" != "0" ]] || [[ "$new_val" != "0" ]]; then + local change="" + local change_indicator="" + + # Calculate numeric change if both values are numbers (including scientific notation) + if [[ "$old_val" =~ ^[0-9]+\.?[0-9]*([eE][+-]?[0-9]+)?$ ]] && [[ "$new_val" =~ ^[0-9]+\.?[0-9]*([eE][+-]?[0-9]+)?$ ]]; then + # Use awk for floating point arithmetic to handle scientific notation + local diff=$(awk "BEGIN {printf \"%.0f\", $new_val - $old_val}") + if [[ $diff -gt 0 ]]; then + change="+$diff" + change_indicator="↑" + elif [[ $diff -lt 0 ]]; then + change="$diff" + change_indicator="↓" + else + change="0" + change_indicator="=" + fi + else + # Non-numeric comparison + if [[ "$old_val" != "$new_val" ]]; then + change="changed" + change_indicator="~" + else + change="same" + change_indicator="=" + fi + fi + + # Don't truncate metric names - show full names + local display_metric="$metric" + + # Format change with arrow indicators (no colors) + local formatted_change="$change $change_indicator" + + printf "%-80s %15s %15s %15s\n" "$display_metric" "$old_val" "$new_val" "$formatted_change" >> "$output_file" + changes_found=1 + fi + done + + if [[ $changes_found -eq 0 ]]; then + echo "" >> "$output_file" + echo "No changes detected in drop counters" >> "$output_file" + else + echo "" >> "$output_file" + echo "Legend: ↑ = increase (potential issue), ↓ = decrease (improvement), = = no change" >> "$output_file" + fi + + # Add note about detailed metrics file + echo "" >> "$output_file" + echo "Note: For full metric details and complete names, see: $new_metrics_file" >> "$output_file" + + return $changes_found +} + +############################################################################### +# MAIN SCRIPT +############################################################################### + +# Check for required commands +for cmd in kubectl curl grep sort; do + if ! command -v $cmd &>/dev/null; then + echo "Error: Required command '$cmd' not found" + exit 1 + fi +done + +# Optional command check +for cmd in lsof; do + if ! command -v $cmd &>/dev/null; then + echo "Warning: Optional command '$cmd' not found, some features may be limited" + fi +done + +# Verify kubectl can connect to the cluster +if ! kubectl get nodes -o name --request-timeout=5s &>/dev/null; then + echo "Error: Cannot connect to Kubernetes cluster. Please check your kubeconfig." + exit 1 +fi + +# Verify the node exists in the cluster +if ! kubectl get nodes -o name --request-timeout=5s | grep -q "${NODE}"; then + echo "Error: Node '${NODE}' not found in the cluster." + echo "Available nodes:" + kubectl get nodes + exit 1 +fi + +# Setup trap for cleanup +trap cleanup EXIT INT TERM + +echo "Watching drop counters on node $NODE (${AGENT_TYPE}) every ${INTERVAL}s..." + +# Local ports for port forwarding +LOCAL_AGENT_PORT=8093 +LOCAL_HUBBLE_PORT=8965 +HUBBLE_PORT=9965 +HUBBLE_ENABLED=0 +HUBBLE_WARNING_SHOWN=0 + +# Files to store metrics for comparison +METRICS_DIR="${TMPDIR:-/tmp}/watchmetrics" +mkdir -p "$METRICS_DIR" +CURRENT_METRICS_FILE="$METRICS_DIR/current_metrics.txt" +PREVIOUS_METRICS_FILE="$METRICS_DIR/previous_metrics.txt" +DIFF_TABLE_FILE="$METRICS_DIR/diff_table.txt" + +# Initialize files if they don't exist +> "$CURRENT_METRICS_FILE" +> "$PREVIOUS_METRICS_FILE" +> "$DIFF_TABLE_FILE" + +debug "Metrics files:" +debug "- Current: $CURRENT_METRICS_FILE" +debug "- Previous: $PREVIOUS_METRICS_FILE" +debug "- Diff Table: $DIFF_TABLE_FILE" + +while true; do + echo -e "\n$(date): Checking ${AGENT_TYPE} drop counters on $NODE" + + # Clear current metrics for this iteration + > "$CURRENT_METRICS_FILE" + + # Get the agent pod on the specified node + echo "Looking for ${AGENT_TYPE} pod on node $NODE..." + AGENT_POD=$(get_agent_pod "$NODE") + + if [[ -z "$AGENT_POD" ]]; then + echo "Error: No ${AGENT_TYPE} pod found on node $NODE" + echo "Checking node existence..." + kubectl get nodes | grep "$NODE" || echo "Node $NODE doesn't exist in the cluster" + echo "Waiting ${INTERVAL}s before next check..." + sleep $INTERVAL + continue + fi + + echo "Found pod: $AGENT_POD" + + # Kill any existing port-forwards + [[ -n "${AGENT_PF_PID:-}" ]] && kill -9 $AGENT_PF_PID 2>/dev/null || true + [[ -n "${HUBBLE_PF_PID:-}" ]] && kill -9 $HUBBLE_PF_PID 2>/dev/null || true + + # Counter for number of iterations with no metrics found + if [[ -z "${NO_METRICS_COUNT:-}" ]]; then + NO_METRICS_COUNT=0 + fi + + # Flag to track if any metrics were found in this iteration + FOUND_ANY_METRICS=0 + + # Setup port forwarding for agent metrics + echo "Setting up port forwarding for agent metrics to port $AGENT_PORT..." + if setup_port_forward "$AGENT_POD" "$LOCAL_AGENT_PORT" "$AGENT_PORT" "AGENT_PF_PID"; then + echo "Port forwarding established for agent metrics" + + # Get and display agent drop metrics + echo "Fetching metrics from http://localhost:$LOCAL_AGENT_PORT/metrics..." + AGENT_METRICS=$(get_metrics "http://localhost:$LOCAL_AGENT_PORT/metrics") + + if [[ -z "$AGENT_METRICS" ]]; then + echo "Warning: No metrics data received from agent endpoint" + fi + + # Try with the standard pattern first + AGENT_DROPS=$(parse_drops "$AGENT_METRICS" "$AGENT_TYPE") + + if [[ -n "$AGENT_DROPS" ]]; then + echo -e "\n=== Agent Drop Counters ===" + echo "$AGENT_DROPS" + FOUND_ANY_METRICS=1 + + # Extract structured metrics for comparison + extract_structured_drops "$AGENT_DROPS" "$AGENT_TYPE" "$CURRENT_METRICS_FILE" + else + echo "No drop counters found in agent metrics" + + # Try again with a fallback pattern focused on errors + FALLBACK_DROPS=$(echo "$AGENT_METRICS" | grep -E "(^${AGENT_TYPE}.*error|^${AGENT_TYPE}.*fail)" | grep -v "0$" | sort) + if [[ -n "$FALLBACK_DROPS" ]]; then + echo -e "\n=== Agent Error Counters (potential drops) ===" + echo "$FALLBACK_DROPS" + FOUND_ANY_METRICS=1 + + # Extract structured metrics for comparison + extract_structured_drops "$FALLBACK_DROPS" "$AGENT_TYPE" "$CURRENT_METRICS_FILE" + elif [[ $DEBUG -eq 1 ]]; then + echo "Sample of received metrics (first 10 lines):" + echo "$AGENT_METRICS" | head -10 + fi + fi + else + echo "Failed to establish port forwarding for agent metrics" + fi + + # Setup port forwarding for Hubble metrics if not disabled + if [[ $HUBBLE_ENABLED -eq 0 || $HUBBLE_WARNING_SHOWN -eq 0 ]]; then + echo "Setting up port forwarding for Hubble metrics to port $HUBBLE_PORT..." + if setup_port_forward "$AGENT_POD" "$LOCAL_HUBBLE_PORT" "$HUBBLE_PORT" "HUBBLE_PF_PID"; then + HUBBLE_ENABLED=1 + + # Get and display Hubble drop metrics + echo "Fetching metrics from http://localhost:$LOCAL_HUBBLE_PORT/metrics..." + HUBBLE_METRICS=$(get_metrics "http://localhost:$LOCAL_HUBBLE_PORT/metrics") + + if [[ -z "$HUBBLE_METRICS" ]]; then + echo "Warning: No metrics data received from Hubble endpoint" + else + # Try with hubble prefix first, then fall back to flow metrics if needed + HUBBLE_DROPS=$(parse_drops "$HUBBLE_METRICS" "hubble" "flow.*drop|flow.*reject") + + if [[ -n "$HUBBLE_DROPS" ]]; then + echo -e "\n=== Hubble Drop Counters ===" + echo "$HUBBLE_DROPS" + FOUND_ANY_METRICS=1 + + # Extract structured metrics for comparison + extract_structured_drops "$HUBBLE_DROPS" "hubble" "$CURRENT_METRICS_FILE" + else + echo "No drop counters found in Hubble metrics" + + if [[ $DEBUG -eq 1 ]]; then + echo "Sample of received Hubble metrics (first 10 lines):" + echo "$HUBBLE_METRICS" | head -10 + + # Try to find flow-related metrics as they might be useful + echo "Looking for flow metrics (might contain useful information):" + FLOW_METRICS=$(echo "$HUBBLE_METRICS" | grep -i "flow" | head -10) + if [[ -n "$FLOW_METRICS" ]]; then + echo "$FLOW_METRICS" + else + echo "No flow metrics found" + fi + fi + fi + fi + else + HUBBLE_ENABLED=0 + if [[ $HUBBLE_WARNING_SHOWN -eq 0 ]]; then + echo "Notice: Hubble port-forwarding failed - Hubble metrics will be ignored" + HUBBLE_WARNING_SHOWN=1 + + if [[ $DEBUG -eq 1 ]]; then + echo "DEBUG: Checking if Hubble is enabled in Cilium..." + kubectl -n $AGENT_NS exec $AGENT_POD -- cilium status | grep -i hubble || echo "Hubble not found in Cilium status" + fi + fi + fi + fi + + # Update metrics counter + if [[ $FOUND_ANY_METRICS -eq 0 ]]; then + NO_METRICS_COUNT=$((NO_METRICS_COUNT + 1)) + + # After 3 attempts with no metrics, provide some help + if [[ $NO_METRICS_COUNT -eq 3 ]]; then + echo -e "\n==================================================================================================" + echo "NOTE: No drop metrics found after multiple attempts. This could be due to:" + echo " 1. There are genuinely no packet drops occurring on this node" + echo " 2. The metrics format used by ${AGENT_TYPE} in your cluster is different than expected" + echo " 3. ${AGENT_TYPE} is not configured to expose drop metrics" + echo "" + if [[ "$AGENT_TYPE" == "cilium" ]]; then + echo "For Cilium, you might want to check:" + echo " - Cilium version: kubectl -n kube-system exec $AGENT_POD -- cilium version" + echo " - Hubble status: kubectl -n kube-system exec $AGENT_POD -- cilium status | grep Hubble" + echo " - Metrics directly: kubectl -n kube-system port-forward $AGENT_POD 9962:9962 & curl localhost:9962/metrics | grep -i drop" + elif [[ "$AGENT_TYPE" == "retina" ]]; then + echo "For Retina, you might want to check:" + echo " - Retina version: kubectl -n kube-system describe pod $AGENT_POD | grep Image" + echo " - Metrics directly: kubectl -n kube-system port-forward $AGENT_POD 10093:10093 & curl localhost:10093/metrics | grep -i drop" + fi + echo "==================================================================================================" + + # Reset counter so we don't show this message too often + NO_METRICS_COUNT=0 + fi + else + # Reset the counter when metrics are found + NO_METRICS_COUNT=0 + + # Generate and display the diff table if we have previous metrics + if [[ -s "$PREVIOUS_METRICS_FILE" && -s "$CURRENT_METRICS_FILE" ]]; then + echo -e "\n=== Metrics Changes Since Last Check ===" + debug "Comparing metrics in $PREVIOUS_METRICS_FILE and $CURRENT_METRICS_FILE" + + # Generate the diff output + generate_diff_table "$PREVIOUS_METRICS_FILE" "$CURRENT_METRICS_FILE" "$DIFF_TABLE_FILE" + + # Display the diff output + if [[ -s "$DIFF_TABLE_FILE" ]]; then + cat "$DIFF_TABLE_FILE" + else + echo " No changes in drop counters since last check" + fi + else + debug "Not generating diff - missing or empty metrics files" + fi + + # Save current metrics as previous for next comparison + if [[ -s "$CURRENT_METRICS_FILE" ]]; then + debug "Saving current metrics for next comparison" + cp "$CURRENT_METRICS_FILE" "$PREVIOUS_METRICS_FILE" + else + debug "Current metrics file is empty, not saving for comparison" + fi + + # Clear current metrics file for next iteration + > "$CURRENT_METRICS_FILE" + fi + + echo -e "\nWaiting ${INTERVAL}s before next check..." + sleep $INTERVAL +done From fdbc98d177feba2b82e898472cc40276cf795286 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 18 Jun 2025 18:34:18 +0100 Subject: [PATCH 044/448] fix(cli): use namespace from user context when --namespace is not set (#1677) # Description Currently when trying to create a capture and `--namespace` is not set, retina-kubectl does not work as expected which would be to create a capture in the namespace set in user's kubectl context. This PR fixes this issue by setting namespace based on user's kubectl context. ## Related Issue Fixes #1579 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Test: ```bash ./artifacts/kubectl-retina capture create --node-names "aks-nodepool1-17156767-vmss000000" --duration 5s --name test ts=2025-06-18T09:20:02.268+0100 level=info caller=capture/create.go:274 msg="Capture timestamp: 2025-06-18 08:20:02 +0000 UTC" ts=2025-06-18T09:20:02.269+0100 level=info caller=capture/create.go:277 msg="The capture duration is set to 5s" ts=2025-06-18T09:20:02.269+0100 level=info caller=capture/create.go:331 msg="The capture file max size is set to 100MB" ts=2025-06-18T09:20:02.269+0100 level=info caller=utils/capture_image.go:57 msg="Using capture workload image ghcr.io/microsoft/retina/retina-agent:v0.0.34-10-g8e41f1b with version determined by CLI version" ts=2025-06-18T09:20:02.276+0100 level=info caller=capture/crd_to_job.go:203 msg="HostPath is not empty" HostPath=/mnt/retina/captures ts=2025-06-18T09:20:03.218+0100 level=info caller=capture/crd_to_job.go:902 msg="The Parsed tcpdump filter is \"\"" ######################### Expected Capture Files ######################### test-aks-nodepool1-17156767-vmss000000-20250618082002UTC.tar.gz Note: The file(s) may not be created if the capture job(s) fail prematurely. ######################### ts=2025-06-18T09:20:03.397+0100 level=info caller=capture/create.go:411 msg="Packet capture job is created" namespace=default capture job=test-n55p4 ts=2025-06-18T09:20:03.397+0100 level=info caller=capture/create.go:148 msg="Please manually delete all capture jobs" NAMESPACE CAPTURE NAME JOB COMPLETIONS AGE default test test-n55p4 0/1 0s ./artifacts/kubectl-retina capture delete --name test ts=2025-06-18T09:20:54.962+0100 level=info caller=capture/delete.go:94 msg="Retina Capture \"test\" delete" ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- cli/cmd/capture/create.go | 10 ++++++++++ cli/cmd/capture/delete.go | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index ecd06174f9..6e1758d41a 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -121,6 +121,16 @@ var createCapture = &cobra.Command{ return errors.Wrap(err, "failed to initialize kubernetes client") } + // Set namespace. If --namespace is not set, use namespace on user's context + ns, _, err := opts.ConfigFlags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return errors.Wrap(err, "failed to get namespace from kubeconfig") + } + + if opts.Namespace == nil || *opts.Namespace == "" { + opts.Namespace = &ns + } + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) defer cancel() diff --git a/cli/cmd/capture/delete.go b/cli/cmd/capture/delete.go index 7cc6cb8a4c..523e359888 100644 --- a/cli/cmd/capture/delete.go +++ b/cli/cmd/capture/delete.go @@ -42,6 +42,16 @@ var deleteCapture = &cobra.Command{ return errors.Wrap(err, "") } + // Set namespace. If --namespace is not set, use namespace on user's context + ns, _, err := opts.ConfigFlags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return errors.Wrap(err, "failed to get namespace from kubeconfig") + } + + if opts.Namespace == nil || *opts.Namespace == "" { + opts.Namespace = &ns + } + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) defer cancel() From 6b9b1f2dbd25d01032acb64dc41d740ddd4d7de6 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 19 Jun 2025 08:02:30 +0100 Subject: [PATCH 045/448] chore(cli): set retina agent image registry at build time (#1685) # Description When a retina capture is created by retina-kubectl CLI, it uses `ghcr.io/microsoft` as registry to pull retina agent image from. This change allows setting at build time what image name should CLI use when creating retina capture jobs. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Logs of tests executed: ```bash # default behavior: use ghcr.io/microsoft as before $ make kubectl-retina-image echo "Building for linux/amd64" Building for linux/amd64 set -e ; \ make container-docker \ PLATFORM=linux/amd64 \ DOCKERFILE=cli/Dockerfile \ REGISTRY=ghcr.io \ IMAGE=microsoft/retina/kubectl-retina \ VERSION=v0.0.34-16-gf04641c \ TAG=v0.0.34-16-gf04641c-linux-amd64 \ CONTEXT_DIR=/home/lx/projects/retina/repositories/official-retina \ EXTRA_BUILD_ARGS= make[1]: Entering directory '/home/lx/projects/retina/repositories/official-retina' # ... $ ./artifacts/kubectl-retina capture create --host-path ~/ --node-names "aks-nodepool1-17156767-vmss000000" --duration 5s -n default # ... $ $ k get po retina-capture-tgq9s-w84q6 -o yaml | grep image: image: ghcr.io/microsoft/retina/retina-agent:v0.0.34-16-gf04641c # new behavior: set image name to be used at build time $ AGENT_IMAGE_NAME=mcr.microsoft.com/containernetworking/retina-agent make kubectl-retina-image echo "Building for linux/amd64" Building for linux/amd64 set -e ; \ make container-docker \ PLATFORM=linux/amd64 \ DOCKERFILE=cli/Dockerfile \ REGISTRY=ghcr.io \ IMAGE=microsoft/retina/kubectl-retina \ VERSION=v0.0.34-16-gf04641c \ TAG=v0.0.34-16-gf04641c-linux-amd64 \ CONTEXT_DIR=/home/lx/projects/retina/repositories/official-retina \ EXTRA_BUILD_ARGS="--build-arg AGENT_IMAGE_NAME=mcr.microsoft.com/containernetworking/retina-agent" # ... $ ./artifacts/kubectl-retina capture create --host-path ~/ --node-names "aks-nodepool1-17156767-vmss000000" --duration 5s -n default # ... $ k get po retina-capture-xqj84-8wlph -o yaml | grep image: image: mcr.microsoft.com/containernetworking/retina-agent:v0.0.34-16-gf04641c ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- Makefile | 9 ++++++++- cli/Dockerfile | 4 +++- internal/buildinfo/buildinfo.go | 1 + pkg/capture/constants/job_specification.go | 10 +++++++--- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 8ae30dabc3..e19a44ee74 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,15 @@ KIND_CLUSTER = retina-cluster WINVER2022 ?= "10.0.20348.1906" WINVER2019 ?= "10.0.17763.4737" APP_INSIGHTS_ID ?= "" +AGENT_IMAGE_NAME ?= "" GENERATE_TARGET_DIRS = \ ./pkg/plugin/linuxutil +# Set agent registry to get image from when using retina-kubectl +ifneq ($(AGENT_IMAGE_NAME), "") + EXTRA_BUILD_ARGS := "--build-arg AGENT_IMAGE_NAME=$(AGENT_IMAGE_NAME)" +endif + # Default platform is linux/amd64 GOOS ?= linux GOARCH ?= amd64 @@ -306,7 +312,8 @@ kubectl-retina-image: IMAGE=$(KUBECTL_RETINA_IMAGE) \ VERSION=$(TAG) \ TAG=$(RETINA_PLATFORM_TAG) \ - CONTEXT_DIR=$(REPO_ROOT) + CONTEXT_DIR=$(REPO_ROOT) \ + EXTRA_BUILD_ARGS=$(EXTRA_BUILD_ARGS) kapinger-image: docker buildx build --builder retina --platform windows/amd64 --target windows-amd64 -t $(IMAGE_REGISTRY)/$(KAPINGER_IMAGE):$(TAG)-windows-amd64 ./hack/tools/kapinger/ --push diff --git a/cli/Dockerfile b/cli/Dockerfile index 5dfd12434c..aeb1c42afc 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -3,6 +3,7 @@ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256: ARG VERSION ARG APP_INSIGHTS_ID +ARG AGENT_IMAGE_NAME="ghcr.io/microsoft/retina/retina-agent" WORKDIR /workspace COPY . . @@ -17,7 +18,8 @@ ENV GOARCH=${GOARCH} RUN --mount=type=cache,target="/root/.cache/go-build" \ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" \ - -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" \ + -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID" \ + -X "github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName"="$AGENT_IMAGE_NAME"" \ -a -o kubectl-retina cli/main.go # mcr.microsoft.com/cbl-mariner/distroless/minimal:2.0 diff --git a/internal/buildinfo/buildinfo.go b/internal/buildinfo/buildinfo.go index 5e090f29e2..9315db7c77 100644 --- a/internal/buildinfo/buildinfo.go +++ b/internal/buildinfo/buildinfo.go @@ -9,4 +9,5 @@ var ( // If it is set, the application will send telemetry to the corresponding Application Insights resource. ApplicationInsightsID string Version string + RetinaAgentImageName = "ghcr.io/microsoft/retina/retina-agent" ) diff --git a/pkg/capture/constants/job_specification.go b/pkg/capture/constants/job_specification.go index cd7da30ea1..5e484d0916 100644 --- a/pkg/capture/constants/job_specification.go +++ b/pkg/capture/constants/job_specification.go @@ -3,6 +3,10 @@ package constants +import ( + "github.com/microsoft/retina/internal/buildinfo" +) + // Capture job specification const ( CaptureHostPathVolumeName string = "hostpath" @@ -35,9 +39,9 @@ const ( // CaptureOutputLocationS3UploadSecretAccessKey is the key of the secret that stores the s3 secret access key. CaptureOutputLocationS3UploadSecretAccessKey string = "s3-secret-access-key" - // CaptureWorkloadImageName defines the official capture workload image repo and image name - CaptureWorkloadImageName string = "ghcr.io/microsoft/retina/retina-agent" - // DebugCaptureWorkloadImageName defines the capture workload image for testing and debugging DebugCaptureWorkloadImageName string = "ghcr.io/microsoft/retina/retina-agent" ) + +// CaptureWorkloadImageName defines the official capture workload image repo and image name +var CaptureWorkloadImageName string = buildinfo.RetinaAgentImageName From 6085726766dd898be5d31f7fec61182ce294794c Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 19 Jun 2025 09:11:55 +0100 Subject: [PATCH 046/448] chore(ci): add build kubectl-retina-mcr (#1695) # Description This PR adds to the `goreleaser.yaml` file the necessary steps to build and release the `kubectl-retina-mcr` binary. This binary references the `mcr.microsoft.com/containernetworking/retina-agent` image. This PR also updates a deprecated option: `format: [zip'` -> `formats: [ 'zip' ]` ref: https://goreleaser.com/deprecations/#archivesformat ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed I tested manually run goreleaser with same environment variables as it should run in pipeline to validate that binary is built and it works as expected: ```bash # current execution of goreleaser $ goreleaser build --snapshot --verbose --clean # ... $ ./dist/retina_linux_amd64_v1/kubectl-retina-linux-amd64 capture create --host-path ~/ --node-names "aks-nodepool1-17156767-vmss000000" --duration 5s -n default # ... $ k get po retina-capture-jtxgw-27l8l -o yaml | grep image: image: ghcr.io/microsoft/retina/retina-agent:v0.0.34-SNAPSHOT-91af0fd # added execution of goreleaser with `AGENT_IMAGE_NAME` and `SUFFIX` env vars: $ AGENT_IMAGE_NAME=mcr.microsoft.com/containernetworking/retina-agent SUFFIX=-mcr goreleaser build --snapshot --verbose --clean # ... $ ./dist/retina_linux_amd64_v1/kubectl-retina-mcr-linux-amd64 capture create --host-path ~/ --node-names "aks-nodepool1-17156767-vmss000000" --duration 5s -n default # ... $ k get po retina-capture-mksfb-szsdk -o yaml | grep image: image: mcr.microsoft.com/containernetworking/retina-agent:v0.0.34-SNAPSHOT-91af0fd ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- .github/workflows/goreleaser.yaml | 44 +++++++++++++++++++++++++++++++ .goreleaser.yaml | 8 ++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 47820d82bf..d7f033ccb5 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -27,6 +27,28 @@ jobs: distribution: goreleaser version: latest args: build --snapshot --clean + build-mcr: + name: Build kubectl-retina-mcr + if: github.ref_type == 'branch' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version-file: go.mod + - name: Run GoReleaser build + uses: goreleaser/goreleaser-action@v6 + env: + AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent + SUFFIX: -mcr + with: + distribution: goreleaser + version: latest + args: build --snapshot --clean release: name: Release kubectl-retina runs-on: ubuntu-latest @@ -51,3 +73,25 @@ jobs: - name: Update new version in krew-index if: github.repository_owner == 'microsoft' uses: rajatjindal/krew-release-bot@v0.0.47 + name: Release kubectl-retina-mcr + runs-on: ubuntu-latest + if: github.ref_type == 'tag' + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version-file: go.mod + - name: Run GoReleaser release + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent + SUFFIX: -mcr diff --git a/.goreleaser.yaml b/.goreleaser.yaml index e7a395b868..d46c7123cb 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -9,7 +9,7 @@ before: - go mod tidy builds: - - binary: kubectl-retina-{{ .Os }}-{{ .Arch }} + - binary: kubectl-retina{{.Env.SUFFIX}}-{{ .Os }}-{{ .Arch }} env: - CGO_ENABLED=0 goarch: @@ -23,6 +23,10 @@ builds: - darwin ldflags: - -X github.com/microsoft/retina/internal/buildinfo.Version=v{{.Version}} + - >- + {{- if index .Env "AGENT_IMAGE_NAME" }} + -X github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName={{.Env.AGENT_IMAGE_NAME}} + {{- end }} main: cli/main.go archives: @@ -30,7 +34,7 @@ archives: wrap_in_directory: false format_overrides: - goos: windows - format: zip + formats: [ 'zip' ] changelog: sort: asc From 0b5dc6e61dc07459a1f531f15a24121c07a82b08 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Jun 2025 11:18:44 +0100 Subject: [PATCH 047/448] feat: Make capturing on all interfaces (-i any) the default behavior for retina captures (#1649) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem Currently, when `kubectl retina capture create` is run without any additional options, retina only captures packets on the first available interface (typically eth0). This limits the visibility of network traffic that may be flowing through other interfaces on the node. ## Solution This PR changes the default behavior to capture on all interfaces by using the `-i any` tcpdump flag when no custom tcpdump filter is specified. This provides better network visibility out of the box while maintaining backward compatibility. ## Changes Made 1. **Modified `pkg/capture/provider/network_capture_unix.go`**: Updated the tcpdump command construction to include `-i any` by default when no raw tcpdump filter is specified. 2. **Added comprehensive tests in `pkg/capture/provider/network_capture_test.go`** to verify: - Default behavior includes `-i any` when no raw filter is set - User-specified raw filters override the default behavior - Backward compatibility is maintained 3. **Updated documentation in `docs/04-Captures/02-cli.md`** to clarify the new default behavior and provide an example of capturing on a specific interface. ## Backward Compatibility Users can still override the default behavior by using the `--tcpdump-filter` flag: ```bash # Capture on all interfaces (new default) kubectl retina capture create --name my-capture # Capture on specific interface (override) kubectl retina capture create --name my-capture --tcpdump-filter="-i eth0" ``` ## Testing All existing tests continue to pass, and new tests verify the correct command construction for both default and override scenarios. Fixes #1648. --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. Signed-off-by: Kamil Co-authored-by: Kamil --- cli/cmd/capture/create.go | 14 ++ crd/api/v1alpha1/capture_types.go | 6 + docs/04-Captures/02-cli.md | 22 +- pkg/capture/capture_manager.go | 2 +- pkg/capture/constants/job_env.go | 3 + pkg/capture/crd_to_job.go | 3 + .../provider/network_capture_common.go | 2 +- pkg/capture/provider/network_capture_test.go | 118 +++++++++- pkg/capture/provider/network_capture_unix.go | 210 +++++++++++------- 9 files changed, 289 insertions(+), 91 deletions(-) diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index 6e1758d41a..33f84fcd45 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -41,6 +41,7 @@ var ( hostPath string includeFilter string includeMetadata bool + interfaces string jobNumLimit int maxSize int namespace string @@ -88,6 +89,9 @@ var createExample = templates.Examples(i18n.T(` # Select nodes using node-selector and set duration to 10s kubectl retina capture create --node-selectors="agentpool=agentpool" --duration=10s + # Capture on specific network interfaces (instead of all interfaces) + kubectl retina capture create --node-selectors="agentpool=agentpool" --interfaces="eth0,eth1" + # Select nodes using node-selector and upload the artifacts to blob storage with SAS URL https://testaccount.blob.core.windows.net/ kubectl retina capture create --node-selectors="agentpool=agentpool" --blob-upload=https://testaccount.blob.core.windows.net/ @@ -337,6 +341,15 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti capture.Spec.CaptureConfiguration.CaptureOption.PacketSize = &packetSize } + if interfaces != "" { + interfaceSlice := strings.Split(interfaces, ",") + for i := range interfaceSlice { + interfaceSlice[i] = strings.TrimSpace(interfaceSlice[i]) + } + retinacmd.Logger.Info(fmt.Sprintf("Capturing on specific interfaces: %v", interfaceSlice)) + capture.Spec.CaptureConfiguration.CaptureOption.Interfaces = interfaceSlice + } + if len(hostPath) != 0 { capture.Spec.OutputConfiguration.HostPath = &hostPath } @@ -505,6 +518,7 @@ func init() { createCapture.Flags().StringVar(&s3AccessKeyID, "s3-access-key-id", "", "S3 access key id to upload capture files") createCapture.Flags().StringVar(&s3SecretAccessKey, "s3-secret-access-key", "", "S3 access secret key to upload capture files") createCapture.Flags().StringVar(&tcpdumpFilter, "tcpdump-filter", "", "Raw tcpdump flags which works only for Linux") + createCapture.Flags().StringVar(&interfaces, "interfaces", "", "Comma-separated list of network interfaces to capture on (e.g., eth0,eth1)") createCapture.Flags().StringVar(&excludeFilter, "exclude-filter", "", "A comma-separated list of IP:Port pairs that are "+ "excluded from capturing network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") createCapture.Flags().StringVar(&includeFilter, "include-filter", "", "A comma-separated list of IP:Port pairs that are "+ diff --git a/crd/api/v1alpha1/capture_types.go b/crd/api/v1alpha1/capture_types.go index 70fab30ace..917305830a 100644 --- a/crd/api/v1alpha1/capture_types.go +++ b/crd/api/v1alpha1/capture_types.go @@ -65,6 +65,12 @@ type CaptureOption struct { // +kubebuilder:default=100 // +optional MaxCaptureSize *int `json:"maxCaptureSize,omitempty"` + + // Interfaces specifies the network interfaces on which to capture packets. + // If specified, captures only on the listed interfaces. + // If empty, captures on all interfaces by default. + // +optional + Interfaces []string `json:"interfaces,omitempty"` } // CaptureTarget indicates the target on which the network packets capture will be performed. diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index 4bb02ae2f5..85aef2f576 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -79,7 +79,8 @@ The network traffic will be uploaded to the specified output location. | `s3-path` | string | retina/captures | Prefix path within the S3 bucket where captures will be stored. | | | `s3-region` | string | "" | Region where the S3 compatible bucket is located. | | | `s3-secret-access-key`| string | "" | S3 access secret key to upload capture files. | | -| `tcpdump-filter` | string | "" | Raw tcpdump flags. Available tcpdump filters can be found in the [TCPDUMP MAN PAGE](https://www.tcpdump.org/manpages/tcpdump.1.html). | Only works on Linux. Includes only tcpdump flags, for boolean expressions, please use include/exclude filters. | +| `interfaces` | string | "" | Comma-separated list of network interfaces to capture on (e.g., "eth0,eth1"). By default, captures are performed on all network interfaces. | | +| `tcpdump-filter` | string | "" | Raw tcpdump flags. Available tcpdump filters can be found in the [TCPDUMP MAN PAGE](https://www.tcpdump.org/manpages/tcpdump.1.html). This overrides interface selection options when specified. | Only works on Linux. Includes only tcpdump flags, for boolean expressions, please use include/exclude filters. | #### Examples @@ -110,6 +111,25 @@ kubectl retina capture create \ --namespace-selectors="kubernetes.io/metadata.name=kube-system" ``` +##### Interface Selection + +Capture on all interfaces (default behavior) + +```sh +kubectl retina capture create \ + --name example-all-interfaces \ + --node-selectors "kubernetes.io/os=linux" +``` + +Capture on specific interfaces + +```sh +kubectl retina capture create \ + --name example-specific-interfaces \ + --node-selectors "kubernetes.io/os=linux" \ + --interfaces "eth0,eth1" +``` + ##### Output Configuration Host Path diff --git a/pkg/capture/capture_manager.go b/pkg/capture/capture_manager.go index c0e5550386..a866bef668 100644 --- a/pkg/capture/capture_manager.go +++ b/pkg/capture/capture_manager.go @@ -174,7 +174,7 @@ func (cm *CaptureManager) OutputCapture(ctx context.Context, srcDir string) erro } if len(errStr) != 0 { - return fmt.Errorf(errStr) + return errors.New(errStr) } // Remove tarball created inside this function. diff --git a/pkg/capture/constants/job_env.go b/pkg/capture/constants/job_env.go index cabc939872..724a0fe78b 100644 --- a/pkg/capture/constants/job_env.go +++ b/pkg/capture/constants/job_env.go @@ -34,5 +34,8 @@ const ( TcpdumpRawFilterEnvKey string = "TCPDUMP_RAW_FILTER" NetshFilterEnvKey string = "NETSH_FILTER" + // Interface selection environment variables + CaptureInterfacesEnvKey string = "CAPTURE_INTERFACES" + ApiserverEnvKey = "APISERVER" ) diff --git a/pkg/capture/crd_to_job.go b/pkg/capture/crd_to_job.go index 358b972483..eeb5b9a000 100644 --- a/pkg/capture/crd_to_job.go +++ b/pkg/capture/crd_to_job.go @@ -934,6 +934,9 @@ func (translator *CaptureToPodTranslator) obtainCaptureOptionEnv(option retinav1 if option.MaxCaptureSize != nil { outputEnv[captureConstants.CaptureMaxSizeEnvKey] = strconv.Itoa(*option.MaxCaptureSize) } + if len(option.Interfaces) > 0 { + outputEnv[captureConstants.CaptureInterfacesEnvKey] = strings.Join(option.Interfaces, ",") + } return outputEnv, nil } diff --git a/pkg/capture/provider/network_capture_common.go b/pkg/capture/provider/network_capture_common.go index ce2cba04fc..9ec42d3a13 100644 --- a/pkg/capture/provider/network_capture_common.go +++ b/pkg/capture/provider/network_capture_common.go @@ -43,7 +43,7 @@ func (ncpc *NetworkCaptureProviderCommon) networkCaptureCommandLog(logFileName s return nil, err } - if _, err := captureCommandLogFile.WriteString(fmt.Sprintf("%s\n\n", captureCommand.String())); err != nil { + if _, err := fmt.Fprintf(captureCommandLogFile, "%s\n\n", captureCommand.String()); err != nil { ncpc.l.Error("Failed to write capture command to file", zap.String("file", captureCommandLogFile.Name()), zap.Error(err)) } diff --git a/pkg/capture/provider/network_capture_test.go b/pkg/capture/provider/network_capture_test.go index b81893239e..b64d1364e0 100644 --- a/pkg/capture/provider/network_capture_test.go +++ b/pkg/capture/provider/network_capture_test.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. @@ -5,19 +7,29 @@ package provider import ( "os" + "os/exec" "strings" "testing" + captureConstants "github.com/microsoft/retina/pkg/capture/constants" "github.com/microsoft/retina/pkg/capture/file" "github.com/microsoft/retina/pkg/log" ) +const ( + testCaptureFilePath = "/tmp/test.pcap" + interfaceEth0 = "eth0" + interfaceEth1 = "eth1" + interfaceAny = "any" + interfaceLo = "lo" +) + func TestSetupAndCleanup(t *testing.T) { captureName := "capture-test" nodeHostName := "node1" timestamp := file.Now() - log.SetupZapLogger(log.GetDefaultLogOpts()) - networkCaptureprovider := &NetworkCaptureProvider{l: log.Logger().Named("test")} + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + networkCaptureprovider := NewNetworkCaptureProvider(log.Logger().Named("test")) tmpFilename := file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} tmpCaptureLocation, err := networkCaptureprovider.Setup(tmpFilename) @@ -37,7 +49,7 @@ func TestSetupAndCleanup(t *testing.T) { t.Errorf("Temporary capture dir name %s should contain timestamp %s", tmpCaptureLocation, timestamp) } - if _, err := os.Stat(tmpCaptureLocation); os.IsNotExist(err) { + if _, statErr := os.Stat(tmpCaptureLocation); os.IsNotExist(statErr) { t.Errorf("Temporary capture dir %s should be created", tmpCaptureLocation) } @@ -50,3 +62,103 @@ func TestSetupAndCleanup(t *testing.T) { t.Errorf("Temporary capture dir %s should be deleted", tmpCaptureLocation) } } + +// Helper function to check if command args contain specific interface +func hasInterface(cmd *exec.Cmd, expectedInterface string) bool { + for i, arg := range cmd.Args { + if arg == "-i" && i+1 < len(cmd.Args) && cmd.Args[i+1] == expectedInterface { + return true + } + } + return false +} + +// Helper function to reset environment variables +func resetEnvVars() { + os.Unsetenv(captureConstants.TcpdumpRawFilterEnvKey) + os.Unsetenv(captureConstants.PacketSizeEnvKey) + os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) +} + +func TestTcpdumpDefaultBehavior(t *testing.T) { + resetEnvVars() + + cmd := constructTcpdumpCommand(testCaptureFilePath) + + if !hasInterface(cmd, interfaceAny) { + t.Errorf("Expected tcpdump command to include '-i any', but got args: %v", cmd.Args) + } +} + +func TestTcpdumpRawFilterOverride(t *testing.T) { + resetEnvVars() + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, "-i "+interfaceEth0) + defer os.Unsetenv(captureConstants.TcpdumpRawFilterEnvKey) + + cmd := constructTcpdumpCommand(testCaptureFilePath) + + if !hasInterface(cmd, interfaceEth0) { + t.Errorf("Expected tcpdump command to include '-i %s' from raw filter, but got args: %v", interfaceEth0, cmd.Args) + } + if hasInterface(cmd, interfaceAny) { + t.Errorf("Expected tcpdump command not to include '-i any' when raw filter is set, but got args: %v", cmd.Args) + } +} + +func TestTcpdumpSpecificInterfaces(t *testing.T) { + resetEnvVars() + os.Setenv(captureConstants.CaptureInterfacesEnvKey, interfaceEth0+","+interfaceEth1) + defer os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) + + cmd := constructTcpdumpCommand(testCaptureFilePath) + + if !hasInterface(cmd, interfaceEth0) { + t.Errorf("Expected tcpdump command to include '-i %s', but got args: %v", interfaceEth0, cmd.Args) + } + if !hasInterface(cmd, interfaceEth1) { + t.Errorf("Expected tcpdump command to include '-i %s', but got args: %v", interfaceEth1, cmd.Args) + } + if hasInterface(cmd, interfaceAny) { + t.Errorf("Expected tcpdump command not to include '-i any' when specific interfaces are set, but got args: %v", cmd.Args) + } +} + +func TestTcpdumpRawFilterPriority(t *testing.T) { + resetEnvVars() + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, "-i "+interfaceLo) + os.Setenv(captureConstants.CaptureInterfacesEnvKey, interfaceEth0+","+interfaceEth1) + defer os.Unsetenv(captureConstants.TcpdumpRawFilterEnvKey) + defer os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) + + cmd := constructTcpdumpCommand(testCaptureFilePath) + + if !hasInterface(cmd, interfaceLo) { + t.Errorf("Expected tcpdump command to include '-i %s' from raw filter, but got args: %v", interfaceLo, cmd.Args) + } + if hasInterface(cmd, interfaceEth0) || hasInterface(cmd, interfaceEth1) { + t.Errorf("Expected tcpdump command not to include specific interfaces when raw filter is set, but got args: %v", cmd.Args) + } +} + +func TestTcpdumpInterfaceOverrideDefault(t *testing.T) { + resetEnvVars() + os.Setenv(captureConstants.CaptureInterfacesEnvKey, interfaceEth0) + defer os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) + + cmd := constructTcpdumpCommand(testCaptureFilePath) + + if !hasInterface(cmd, interfaceEth0) { + t.Errorf("Expected tcpdump command to include '-i %s' from specific interfaces, but got args: %v", interfaceEth0, cmd.Args) + } + if hasInterface(cmd, interfaceAny) { + t.Errorf("Expected tcpdump command not to include '-i any' when specific interfaces are set, but got args: %v", cmd.Args) + } +} + +func TestTcpdumpCommandConstruction(t *testing.T) { + t.Run("DefaultBehaviorIncludesAnyInterface", TestTcpdumpDefaultBehavior) + t.Run("RawFilterOverridesDefault", TestTcpdumpRawFilterOverride) + t.Run("SpecificInterfaceSelection", TestTcpdumpSpecificInterfaces) + t.Run("RawFilterOverridesSpecificInterfaces", TestTcpdumpRawFilterPriority) + t.Run("SpecificInterfacesOverrideDefault", TestTcpdumpInterfaceOverrideDefault) +} diff --git a/pkg/capture/provider/network_capture_unix.go b/pkg/capture/provider/network_capture_unix.go index 5027d50b42..c6b966713d 100644 --- a/pkg/capture/provider/network_capture_unix.go +++ b/pkg/capture/provider/network_capture_unix.go @@ -7,6 +7,7 @@ package provider import ( "context" + "errors" "fmt" "os" "os/exec" @@ -23,6 +24,55 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +var ( + errTcpdumpCommandNotConstructed = errors.New("tcpdump command is not constructed with expected arguments") + errTcpdumpStopFailed = errors.New("tcpdump stop failed") +) + +// constructTcpdumpCommand creates a tcpdump command with the appropriate arguments +// based on environment variables for raw filter, specific interfaces, or default behavior +func constructTcpdumpCommand(captureFilePath string) *exec.Cmd { + // NOTE(mainred): The tcpdump release of debian:bullseye image, which is for preparing clang and tools, runs as + // tcpdump user by default for savefiles for output, but when the binary and library are copied to the distroless + // base image, we lost tcpdump user, and the following error will be raised when running tcpdump in our capture pod. + // tcpdump: Couldn't find user 'tcpdump' + // To disable this behavior, we use `--relinquish-privileges=root` same as `-Z root`. + // ref: https://manpages.debian.org/bullseye/tcpdump/tcpdump.8.en.html#Z + captureStartCmd := exec.Command( + "tcpdump", + "-w", captureFilePath, + "--relinquish-privileges=root", + ) + + if packetSize := os.Getenv(captureConstants.PacketSizeEnvKey); packetSize != "" { + captureStartCmd.Args = append( + captureStartCmd.Args, + "-s", packetSize, + ) + } + + // If we set flag and value into the arg item of args, the space between flag and value will not treated as part of + // value, for example, "-i eth0" will be treated as "-i" and " eth0", thus brings a tcpdump unknown interface error. + if tcpdumpRawFilter := os.Getenv(captureConstants.TcpdumpRawFilterEnvKey); tcpdumpRawFilter != "" { + tcpdumpRawFilterSlice := strings.Split(tcpdumpRawFilter, " ") + captureStartCmd.Args = append(captureStartCmd.Args, tcpdumpRawFilterSlice...) + } else if specificInterfaces := os.Getenv(captureConstants.CaptureInterfacesEnvKey); specificInterfaces != "" { + // Use specific interfaces if provided + interfaceList := strings.Split(specificInterfaces, ",") + for _, iface := range interfaceList { + iface = strings.TrimSpace(iface) + if iface != "" { + captureStartCmd.Args = append(captureStartCmd.Args, "-i", iface) + } + } + } else { + // Default to capturing on all interfaces if no raw tcpdump filter or specific interfaces are specified + captureStartCmd.Args = append(captureStartCmd.Args, "-i", "any") + } + + return captureStartCmd +} + type NetworkCaptureProvider struct { NetworkCaptureProviderCommon TmpCaptureDir string @@ -65,7 +115,7 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil captureFilePath := filepath.Join(ncp.TmpCaptureDir, captureFileName) // Remove the folder in case it already exists to mislead the file size check. - os.Remove(captureFilePath) //nolint:errcheck + os.Remove(captureFilePath) //nolint:errcheck // File may not exist, ok to ignore error // NOTE(mainred): The tcpdump release of debian:bullseye image, which is for preparing clang and tools, runs as // tcpdump user by default for savefiles for output, but when the binary and library are copied to the distroless @@ -73,27 +123,9 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil // tcpdump: Couldn't find user 'tcpdump' // To disable this behavior, we use `--relinquish-privileges=root` same as `-Z root`. // ref: https://manpages.debian.org/bullseye/tcpdump/tcpdump.8.en.html#Z - captureStartCmd := exec.Command( - "tcpdump", - "-w", captureFilePath, - "--relinquish-privileges=root", - ) - - if packetSize := os.Getenv(captureConstants.PacketSizeEnvKey); len(packetSize) != 0 { - captureStartCmd.Args = append( - captureStartCmd.Args, - "-s", packetSize, - ) - } - - // If we set flag and value into the arg item of args, the space between flag and value will not treated as part of - // value, for example, "-i eth0" will be treated as "-i" and " eth0", thus brings a tcpdump unknown interface error. - if tcpdumpRawFilter := os.Getenv(captureConstants.TcpdumpRawFilterEnvKey); len(tcpdumpRawFilter) != 0 { - tcpdumpRawFilterSlice := strings.Split(tcpdumpRawFilter, " ") - captureStartCmd.Args = append(captureStartCmd.Args, tcpdumpRawFilterSlice...) - } + captureStartCmd := constructTcpdumpCommand(captureFilePath) - if len(filter) != 0 { + if filter != "" { captureStartCmd.Args = append( captureStartCmd.Args, filter, @@ -109,10 +141,10 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil // Store tcpdpump log as part of capture artifacts. defer func() { - if tcpdumpLog, err := os.ReadFile(tcpdumpLogFile.Name()); err != nil { - ncp.l.Warn("Failed to read tcpdump log", zap.Error(err)) + if tcpdumpLog, readErr := os.ReadFile(tcpdumpLogFile.Name()); readErr != nil { + ncp.l.Warn("Failed to read tcpdump log", zap.Error(readErr)) } else { - ncp.l.Info(fmt.Sprintf("Tcpdump command output: %s", string(tcpdumpLog))) + ncp.l.Info("Tcpdump command output: " + string(tcpdumpLog)) } tcpdumpLogFile.Close() }() @@ -145,18 +177,18 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil go func() { // Chances are that the capture file is not created when we check the file size. time.Sleep(time.Second * time.Duration(fileSizeCheckIntervalInSecond)) - captureFile, err := os.Open(captureFilePath) - if err != nil { - ncp.l.Error("Failed to open capture file", zap.String("capture file path", captureFilePath), zap.Error(err)) + captureFile, openErr := os.Open(captureFilePath) + if openErr != nil { + ncp.l.Error("Failed to open capture file", zap.String("capture file path", captureFilePath), zap.Error(openErr)) ncp.l.Error("Please make sure tcpdump command is constructed with expected arguments", zap.String("tcpdump args", fmt.Sprintf("%+q", captureStartCmd.Args))) - errChan <- fmt.Errorf("tcpdump command is not constructed with expected arguments") + errChan <- errTcpdumpCommandNotConstructed return } for { - fileStat, err := captureFile.Stat() - if err != nil { - ncp.l.Error("Failed to get capture file info", zap.String("capture file path", captureFilePath), zap.Error(err)) + fileStat, statErr := captureFile.Stat() + if statErr != nil { + ncp.l.Error("Failed to get capture file info", zap.String("capture file path", captureFilePath), zap.Error(statErr)) continue } fileSizeBytes := fileStat.Size() @@ -174,16 +206,16 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil case <-doneChan: case <-ctx.Done(): ncp.l.Info("Tcpdump will be stopped - got OS signal, or timeout reached", zap.Error(ctx.Err())) - case err := <-errChan: - return err + case captureErr := <-errChan: + return captureErr } ncp.l.Info("Stop tcpdump") // Kill signal will not wait until the process has actually existed, thus the captured network packets may not be // flushed to the capture file. Instead, we signal terminate and wait until the process to exit. - if err := captureStartCmd.Process.Signal(syscall.SIGTERM); err != nil { - ncp.l.Error("Failed to signal terminate to process, will kill the process", zap.Error(err)) + if signalErr := captureStartCmd.Process.Signal(syscall.SIGTERM); signalErr != nil { + ncp.l.Error("Failed to signal terminate to process, will kill the process", zap.Error(signalErr)) if killErr := captureStartCmd.Process.Kill(); killErr != nil { - return fmt.Errorf("tcpdump stop failed, error: %s", killErr) + return fmt.Errorf("%w: %w", errTcpdumpStopFailed, killErr) } return err } @@ -206,8 +238,8 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { iptablesMode := obtainIptablesMode() ncp.l.Info(fmt.Sprintf("Iptables mode %s is used", iptablesMode)) - iptablesSaveCmdName := fmt.Sprintf("iptables-%s-save", iptablesMode) - iptablesCmdName := fmt.Sprintf("iptables-%s", iptablesMode) + iptablesSaveCmdName := "iptables-" + iptablesMode + "-save" + iptablesCmdName := "iptables-" + iptablesMode metadataList := []struct { commands []command @@ -299,55 +331,11 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { } for _, metadata := range metadataList { - if len(metadata.fileName) != 0 { - captureMetadataFilePath := filepath.Join(ncp.TmpCaptureDir, metadata.fileName) - outfile, err := os.OpenFile(captureMetadataFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) - if err != nil { - ncp.l.Error("Failed to create metadata file", zap.String("metadata file path", captureMetadataFilePath), zap.Error(err)) - continue - } - defer outfile.Close() - - if _, err := outfile.WriteString("Summary:\n\n"); err != nil { - ncp.l.Error("Failed to write summary to file", zap.String("file", outfile.Name()), zap.Error(err)) - } - - // Print headlines for all commands in output file. - cmds := []*exec.Cmd{} - for _, command := range metadata.commands { - cmd := exec.Command(command.name, command.args...) - cmds = append(cmds, cmd) - commandSummary := fmt.Sprintf("%s(%s)\n", cmd.String(), command.description) - if _, err := outfile.WriteString(commandSummary); err != nil { - ncp.l.Error("Failed to write command description to file", zap.String("file", outfile.Name()), zap.Error(err)) - } - } - - if _, err := outfile.WriteString("\nExecute:\n\n"); err != nil { - ncp.l.Error("Failed to write command output to file", zap.String("file", outfile.Name()), zap.Error(err)) - } - - // Write command stdout and stderr to output file - for _, cmd := range cmds { - if _, err := outfile.WriteString(fmt.Sprintf("%s\n\n", cmd.String())); err != nil { - ncp.l.Error("Failed to write string to file", zap.String("file", outfile.Name()), zap.Error(err)) - } - - cmd.Stdout = outfile - cmd.Stderr = outfile - if err := cmd.Run(); err != nil { - // Don't return for error to continue capturing following network metadata. - ncp.l.Error("Failed to execute command", zap.String("command", cmd.String()), zap.Error(err)) - // Log the error in output file because this error does not stop capture job pod from finishing, - // and the job can be recycled automatically leaving no info to debug. - if _, err = outfile.WriteString(fmt.Sprintf("Failed to run %q, error: %s)", cmd.String(), err.Error())); err != nil { - ncp.l.Error("Failed to write command run failure", zap.String("command", cmd.String()), zap.Error(err)) - } - } - } + if metadata.fileName != "" { + ncp.processMetadataFile(metadata) } else { for _, command := range metadata.commands { - cmd := exec.Command(command.name, command.args...) + cmd := exec.Command(command.name, command.args...) // #nosec G204 -- commands are predefined system utilities with safe arguments // Errors will when copying kernel networking configuration for not all files under /proc/sys/net are // readable, like '/proc/sys/net/ipv4/route/flush', which doesn't implement the read function. if output, err := cmd.CombinedOutput(); err != nil { @@ -363,6 +351,58 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { return nil } +func (ncp *NetworkCaptureProvider) processMetadataFile(metadata struct { + commands []command + fileName string +}, +) { + captureMetadataFilePath := filepath.Join(ncp.TmpCaptureDir, metadata.fileName) + outfile, err := os.OpenFile(captureMetadataFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + ncp.l.Error("Failed to create metadata file", zap.String("metadata file path", captureMetadataFilePath), zap.Error(err)) + return + } + defer outfile.Close() + + if _, err := outfile.WriteString("Summary:\n\n"); err != nil { + ncp.l.Error("Failed to write summary to file", zap.String("file", outfile.Name()), zap.Error(err)) + } + + // Print headlines for all commands in output file. + cmds := []*exec.Cmd{} + for _, command := range metadata.commands { + cmd := exec.Command(command.name, command.args...) // #nosec G204 -- commands are predefined system utilities with safe arguments + cmds = append(cmds, cmd) + commandSummary := fmt.Sprintf("%s(%s)\n", cmd.String(), command.description) + if _, err := outfile.WriteString(commandSummary); err != nil { + ncp.l.Error("Failed to write command description to file", zap.String("file", outfile.Name()), zap.Error(err)) + } + } + + if _, err := outfile.WriteString("\nExecute:\n\n"); err != nil { + ncp.l.Error("Failed to write command output to file", zap.String("file", outfile.Name()), zap.Error(err)) + } + + // Write command stdout and stderr to output file + for _, cmd := range cmds { + if _, err := fmt.Fprintf(outfile, "%s\n\n", cmd.String()); err != nil { + ncp.l.Error("Failed to write string to file", zap.String("file", outfile.Name()), zap.Error(err)) + } + + cmd.Stdout = outfile + cmd.Stderr = outfile + if err := cmd.Run(); err != nil { + // Don't return for error to continue capturing following network metadata. + ncp.l.Error("Failed to execute command", zap.String("command", cmd.String()), zap.Error(err)) + // Log the error in output file because this error does not stop capture job pod from finishing, + // and the job can be recycled automatically leaving no info to debug. + if _, err = fmt.Fprintf(outfile, "Failed to run %q, error: %s)", cmd.String(), err.Error()); err != nil { + ncp.l.Error("Failed to write command run failure", zap.String("command", cmd.String()), zap.Error(err)) + } + } + } +} + func (ncp *NetworkCaptureProvider) Cleanup() error { ncp.l.Info("Cleanup network capture", zap.String("capture name", ncp.CaptureName), zap.String("temporary dir", ncp.TmpCaptureDir)) ncp.NetworkCaptureProviderCommon.Cleanup() From 586a3a688c488c410f40f4ce78dc99e0ad857e53 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 19 Jun 2025 12:51:02 +0100 Subject: [PATCH 048/448] chore(shell): add bpftool to shell image (#1696) # Description Add bpftool to retina shell image ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ![image](https://github.com/user-attachments/assets/91c29d1e-bfdc-4b1c-a0fe-b9d221429b6c) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Kamil Co-authored-by: Kamil Co-authored-by: kamilprz <36544756+kamilprz@users.noreply.github.com> --- shell/Dockerfile | 1 + shell/README.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/shell/Dockerfile b/shell/Dockerfile index 896eb5b0b8..d530bf6635 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -25,6 +25,7 @@ RUN tdnf install -y \ wget \ tar \ file \ + bpftool \ && tdnf clean all # Re-use existing arg from Makefile target "container-docker" diff --git a/shell/README.md b/shell/README.md index 1013f8b8a2..abe3251a7b 100644 --- a/shell/README.md +++ b/shell/README.md @@ -5,6 +5,7 @@ Retina CLI provides a command to launch an interactive shell in a node or pod fo * The CLI command `kubectl retina shell` creates a pod with `HostNetwork=true` (for node debugging) or an ephemeral container in an existing pod (for pod debugging). * The container runs an image built from the Dockerfile in this directory. The image is based on Azure Linux and includes commonly-used networking tools. * The [pwru](https://github.com/cilium/pwru) tool is bundled in the image for advanced kernel packet tracing. +* bpftool is also included for eBPF debugging. For testing, you can override the image used by `retina shell` either with CLI arguments (`--retina-shell-image-repo` and `--retina-shell-image-version`) or environment variables @@ -12,9 +13,9 @@ For testing, you can override the image used by `retina shell` either with CLI a Run `kubectl retina shell -h` for full documentation and examples. -## Example: Running pwru +## Example: Running pwru and bpftool -To use `pwru` inside the retina shell, you must grant the following Linux capabilities to the container: +To use `pwru` and `bpftool` inside the retina shell, you must grant the following Linux capabilities to the container: * `NET_ADMIN` * `SYS_ADMIN` @@ -32,6 +33,7 @@ Once inside the shell, you can run: ```sh pwru --help +bpftool --help ``` Currently only Linux is supported; Windows support will be added in the future. From bdd0b28284a29a4e196e098df50cd074dfc25615 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Mon, 23 Jun 2025 10:04:13 +0100 Subject: [PATCH 049/448] fix(test): fix unit tests in pkg capture (#1698) # Description Unit tests for this pkg were failing. E.g. https://github.com/microsoft/retina/actions/runs/15751219397/job/44396605626 ![image](https://github.com/user-attachments/assets/a14ae577-1915-40be-9dc8-ffefeba1ff02) This PR fixes problems in pkg. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Unit test for pkg: ```bash $ go test ./pkg/capture/... ok github.com/microsoft/retina/pkg/capture 0.505s ? github.com/microsoft/retina/pkg/capture/constants [no test files] ? github.com/microsoft/retina/pkg/capture/file [no test files] ok github.com/microsoft/retina/pkg/capture/outputlocation 0.007s ? github.com/microsoft/retina/pkg/capture/outputlocation/managed [no test files] ok github.com/microsoft/retina/pkg/capture/provider 0.006s ok github.com/microsoft/retina/pkg/capture/utils 0.009s ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos Signed-off-by: Alex Castilio Signed-off-by: Kamil Co-authored-by: Kamil --- pkg/capture/capture_manager.go | 11 ++-- pkg/capture/capture_manager_test.go | 4 +- pkg/capture/crd_to_job_test.go | 81 ++++++++++++++++++++++++----- pkg/capture/utils/annotations.go | 6 ++- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/pkg/capture/capture_manager.go b/pkg/capture/capture_manager.go index a866bef668..efcf509c7a 100644 --- a/pkg/capture/capture_manager.go +++ b/pkg/capture/capture_manager.go @@ -23,7 +23,6 @@ import ( captureProvider "github.com/microsoft/retina/pkg/capture/provider" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/telemetry" - "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -109,7 +108,7 @@ func (cm *CaptureManager) captureNodeHostName() string { func (cm *CaptureManager) captureStartTimestamp() (*metav1.Time, error) { timestamp, err := file.StringToTime((os.Getenv(captureConstants.CaptureStartTimestampEnvKey))) if err != nil { - return nil, errors.Wrap(err, "failed to parse timestamp") + return nil, fmt.Errorf("failed to parse timestamp: %w", err) } return timestamp, nil } @@ -156,7 +155,7 @@ func (cm *CaptureManager) captureMaxSizeMB() (int, error) { } func (cm *CaptureManager) OutputCapture(ctx context.Context, srcDir string) error { - var errStr string + var errs error if _, err := os.Stat(srcDir); os.IsNotExist(err) { return fmt.Errorf("capture source directory %s does not exist", srcDir) @@ -169,12 +168,12 @@ func (cm *CaptureManager) OutputCapture(ctx context.Context, srcDir string) erro for _, location := range cm.enabledOutputLocations() { if err := location.Output(ctx, dstTarGz); err != nil { - errStr = errStr + fmt.Sprintf("location %q output error: %s\n", location.Name(), err) + errs = fmt.Errorf("%w; location %q output error: %w", errs, location.Name(), err) } } - if len(errStr) != 0 { - return errors.New(errStr) + if errs != nil { + return fmt.Errorf("failed to enable output locations: %w", errs) } // Remove tarball created inside this function. diff --git a/pkg/capture/capture_manager_test.go b/pkg/capture/capture_manager_test.go index affa0e560c..9649a56665 100644 --- a/pkg/capture/capture_manager_test.go +++ b/pkg/capture/capture_manager_test.go @@ -36,7 +36,7 @@ func TestCaptureNetwork(t *testing.T) { maxSize := 100 os.Setenv(captureConstants.CaptureNameEnvKey, captureName) os.Setenv(captureConstants.NodeHostNameEnvKey, nodeHostName) - os.Setenv(captureConstants.CaptureStartTimestampEnvKey, timestamp.String()) + os.Setenv(captureConstants.CaptureStartTimestampEnvKey, file.TimeToString(timestamp)) os.Setenv(captureConstants.TcpdumpFilterEnvKey, filter) os.Setenv(captureConstants.CaptureDurationEnvKey, "10s") os.Setenv(captureConstants.CaptureMaxSizeEnvKey, strconv.Itoa(maxSize)) @@ -54,7 +54,7 @@ func TestCaptureNetwork(t *testing.T) { defer cancel() tmpFilename := file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} - networkCaptureProvider.EXPECT().Setup(tmpFilename).Return(fmt.Sprintf("%s-%s-%s", captureName, nodeHostName, ×tamp), nil).Times(1) + networkCaptureProvider.EXPECT().Setup(tmpFilename).Return(fmt.Sprintf("%s-%s-%s", captureName, nodeHostName, timestamp), nil).Times(1) networkCaptureProvider.EXPECT().CaptureNetworkPacket(ctx, filter, duration, maxSize).Return(nil).Times(1) _, err := cm.CaptureNetwork(ctx) diff --git a/pkg/capture/crd_to_job_test.go b/pkg/capture/crd_to_job_test.go index 19c49f1be5..df5eeae735 100644 --- a/pkg/capture/crd_to_job_test.go +++ b/pkg/capture/crd_to_job_test.go @@ -679,10 +679,20 @@ func Test_CaptureToPodTranslator_RenderJob_NodeSelected(t *testing.T) { k8sClient := fakeclientset.NewSimpleClientset() log.SetupZapLogger(log.GetDefaultLogOpts()) captureToPodTranslator := NewCaptureToPodTranslatorForTest(k8sClient) + + startTime := time.Now() + + hostPath := "/tmp/capture" // nolint:goconst // Test case needs a var + err := captureToPodTranslator.initJobTemplate(ctx, &retinav1alpha1.Capture{ Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{}, - OutputConfiguration: retinav1alpha1.OutputConfiguration{}, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + HostPath: &hostPath, + }, + }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: &metav1.Time{Time: startTime}, }, }) if err != nil { @@ -861,6 +871,14 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { label.CaptureNameLabel: captureName, label.AppLabel: captureConstants.CaptureContainername, }, + Annotations: map[string]string{ + captureConstants.CaptureFilenameAnnotationKey: (&file.CaptureFilename{ + CaptureName: captureName, + NodeHostname: "node1", + StartTimestamp: timestamp, + }).String(), + captureConstants.CaptureTimestampAnnotationKey: file.TimeToString(timestamp), + }, }, Spec: corev1.PodSpec{ HostNetwork: true, @@ -961,6 +979,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1005,7 +1026,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, { @@ -1092,6 +1113,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1134,7 +1158,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim), Value: pvc}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, @@ -1164,6 +1188,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1206,7 +1233,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim), Value: pvc}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, @@ -1235,6 +1262,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1292,7 +1322,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim), Value: pvc}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, @@ -1316,11 +1346,14 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, }, { - name: "tcpdumpfilter: pod ip adddress and tcpdumpfilter coexist", + name: "tcpdumpfilter: pod ip address and tcpdumpfilter coexist", capture: retinav1alpha1.Capture{ ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1374,7 +1407,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, {Name: captureConstants.TcpdumpRawFilterEnvKey, Value: "-i eth0"}, @@ -1399,6 +1432,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1451,7 +1487,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, {Name: captureConstants.TcpdumpFilterEnvKey, Value: "(host 10.225.0.4)"}, @@ -1475,6 +1511,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1530,7 +1569,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, {Name: captureConstants.TcpdumpFilterEnvKey, Value: "(host 10.225.0.4 or host fd5c:d9f1:79c5:fd83::21e)"}, @@ -1554,6 +1593,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1609,7 +1651,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, {Name: captureConstants.NetshFilterEnvKey, Value: "IPv4.Address=(10.225.0.4) IPv6.Address=(fd5c:d9f1:79c5:fd83::21e)"}, @@ -1629,11 +1671,14 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { isWindows: true, }, { - name: "netshfilter: pod ip adddress and tcpdumpfilter coexist", + name: "netshfilter: pod ip address and tcpdumpfilter coexist", capture: retinav1alpha1.Capture{ ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1687,7 +1732,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, - {Name: captureConstants.CaptureStartTimestampEnvKey, Value: timestamp.String()}, + {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, {Name: captureConstants.TcpdumpRawFilterEnvKey, Value: "-i eth0"}, @@ -1761,6 +1806,10 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { job.Spec.Template.Spec.Containers[0].Command = []string{captureConstants.CaptureContainerEntrypointWin} } + if tt.capture.Spec.OutputConfiguration.HostPath != nil { + job.Spec.Template.Annotations[captureConstants.CaptureHostPathAnnotationKey] = hostPath + } + cmpOption := cmp.Options{ cmpopts.SortSlices(func(enVar1, enVar2 corev1.EnvVar) bool { return enVar1.Name < enVar2.Name }), cmp.Comparer(func(x, y corev1.EnvVar) bool { @@ -1782,6 +1831,8 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs_JobNumLimit(t *testing.T ctx, cancel := TestContext(t) defer cancel() + timestamp := file.Now() + captureName := "capture-test" hostPath := "/tmp/capture" cases := []struct { @@ -1797,6 +1848,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs_JobNumLimit(t *testing.T ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ @@ -1831,6 +1885,9 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs_JobNumLimit(t *testing.T ObjectMeta: metav1.ObjectMeta{ Name: captureName, }, + Status: retinav1alpha1.CaptureStatus{ + StartTime: timestamp, + }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ CaptureTarget: retinav1alpha1.CaptureTarget{ diff --git a/pkg/capture/utils/annotations.go b/pkg/capture/utils/annotations.go index afb4fee8ce..6723270843 100644 --- a/pkg/capture/utils/annotations.go +++ b/pkg/capture/utils/annotations.go @@ -11,8 +11,10 @@ import ( func GetPodAnnotationsFromCapture(capture *retinav1alpha1.Capture) map[string]string { annotations := map[string]string{ - captureConstants.CaptureFilenameAnnotationKey: capture.Name, - captureConstants.CaptureTimestampAnnotationKey: file.TimeToString(capture.Status.StartTime), + captureConstants.CaptureFilenameAnnotationKey: capture.Name, + } + if capture.Status.StartTime != nil { + annotations[captureConstants.CaptureTimestampAnnotationKey] = file.TimeToString(capture.Status.StartTime) } if capture.Spec.OutputConfiguration.HostPath != nil { annotations[captureConstants.CaptureHostPathAnnotationKey] = *capture.Spec.OutputConfiguration.HostPath From 002dc4e71d671e40e5d98313a81f4ef0eee5f111 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Mon, 23 Jun 2025 16:11:29 +0100 Subject: [PATCH 050/448] chore: Update Go version to 1.24.4 (#1701) # Description Updating Go version to 1.24.4 from 1.24.2-2, to fix CVEs. ## Related Issue https://github.com/microsoft/retina/security/code-scanning ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Additional Notes `> trivy image ghcr.io/microsoft/retina/retina-agent:586a3a6` ![{4BABA863-A5CF-4C28-B803-1A4E64D6B5B2}](https://github.com/user-attachments/assets/c1042347-bd56-4815-8b17-779848e07b5a) ![{AEBD498D-C226-417E-9628-842E1CCF5C20}](https://github.com/user-attachments/assets/1fc0f5a4-001b-4ad6-96f7-7e922d1001de) --------- Signed-off-by: Kamil --- cli/Dockerfile | 4 ++-- controller/Dockerfile | 4 ++-- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-2019 | 4 ++-- controller/Dockerfile.windows-2022 | 4 ++-- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 4 ++-- hack/tools/kapinger/Dockerfile | 2 +- hack/tools/toolbox/Dockerfile | 2 +- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2019 | 4 ++-- operator/Dockerfile.windows-2022 | 4 ++-- test/image/Dockerfile | 4 ++-- 14 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index aeb1c42afc..11e2a864c3 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index c3bf86331a..021740df7f 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -2,8 +2,8 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS golang # skopeo inspect docker://mcr.microsoft.com/cbl-mariner/base/core:2.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/cbl-mariner/base/core@sha256:8deab931d4af66264253cce66471a04742dc6f8d5d175d4c18e930eda615c0aa AS mariner-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 3097165c89..ab8b0b66c4 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index f6ba587974..1a9961d7f2 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index 882cac36e7..aa611c8737 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder # Build args ARG VERSION diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 0697cb69d5..9613edc936 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder # Build args ARG VERSION diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index ad35301c04..29ed0063ee 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-windowsservercore-ltsc2022 --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:0fb2afcf9c877c90ca609984303da41846c447ca62c0f9e42046be113cae117e AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:b156a5187b5d22ca866fe14fd232b0de04da111394507fe96efb21e75484fbe6 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index aaddce7c61..67a1f0b67c 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-windowsservercore-ltsc2022 --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:0fb2afcf9c877c90ca609984303da41846c447ca62c0f9e42046be113cae117e AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:b156a5187b5d22ca866fe14fd232b0de04da111394507fe96efb21e75484fbe6 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 97394bac09..45aa1e2af5 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2 AS builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.4 AS builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index ab2a9f4c13..e069c5b054 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.4 AS build ADD . . WORKDIR /go/toolbox/ RUN CGO_ENABLED=0 GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 7fd3c0b3b3..11a8650cc1 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index b9a28bb094..3fbc78cbb1 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder # Build args ARG VERSION diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index deccdca314..aab0dc48fa 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index b17e6e4004..6eca2d3df4 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.2-2-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:5341a0010ecff114ee2f11f5eaa4f73b721b54142954041523f3e785d5c4b978 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder ENV CGO_ENABLED=0 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 51ac04432e1b760b65562154ca3b1227ab09ea07 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Tue, 24 Jun 2025 08:48:05 +0100 Subject: [PATCH 051/448] chore: Bump Hubble to v1.17.5 (#1703) # Description Bump Hubble version - 1.17.5 - to fix CVE. ## Related Issue ![{AF7E32FD-D042-4AC6-9B38-A9E2AC66B19F}](https://github.com/user-attachments/assets/a8082ea5-4541-41b1-adf3-6c1d0acfc905) ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots ![{B71D7FD8-C03D-42AF-83D1-8C1185630521}](https://github.com/user-attachments/assets/12070ffa-cd43-43e7-bedc-550897ff02ba) --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Kamil --- Makefile | 2 +- controller/Dockerfile | 2 +- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index e19a44ee74..4b89477c52 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ PLATFORM ?= $(OS)/$(ARCH) PLATFORMS ?= linux/amd64 linux/arm64 windows/amd64 OS_VERSION ?= ltsc2019 -HUBBLE_VERSION ?= v1.17.3 +HUBBLE_VERSION ?= v1.17.5 CONTAINER_BUILDER ?= docker CONTAINER_RUNTIME ?= docker diff --git a/controller/Dockerfile b/controller/Dockerfile index 021740df7f..c4c315583a 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -99,7 +99,7 @@ RUN arr="clang tcpdump ip ss iptables-legacy iptables-legacy-save iptables-nft i ARG GOARCH=amd64 ENV HUBBLE_ARCH=${GOARCH} # ARG HUBBLE_VERSION may be modified via the update-hubble GitHub Action -ARG HUBBLE_VERSION=v1.17.3 +ARG HUBBLE_VERSION=v1.17.5 ENV HUBBLE_VERSION=${HUBBLE_VERSION} RUN echo "Hubble version: $HUBBLE_VERSION" && \ wget --no-check-certificate https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz && \ diff --git a/go.mod b/go.mod index 7c0f7a389e..261f0e2dff 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/microsoft/retina go 1.24.2 require ( - github.com/go-chi/chi/v5 v5.2.1 + github.com/go-chi/chi/v5 v5.2.2 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.22.0 github.com/spf13/cobra v1.9.1 diff --git a/go.sum b/go.sum index d169779ec3..9ca922e393 100644 --- a/go.sum +++ b/go.sum @@ -571,8 +571,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= -github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= +github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= From 192ddfb5326b4a7cf50e279e2002c45f67f965c9 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:28:26 +0100 Subject: [PATCH 052/448] fix: Goreleaser job (#1706) # Description Goreleaser job had an issue introduced in https://github.com/microsoft/retina/pull/1695 ## Related Issue ![{B14D043B-256E-4AE6-80B2-9DAD642CF0E6}](https://github.com/user-attachments/assets/6775feaa-f844-4a17-9d8d-1a152cc80c4d) ![{3346F450-D6FD-48EB-A03F-B5C41CE42DDC}](https://github.com/user-attachments/assets/82689e34-03cb-4143-9971-78c19e69d6ab) ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Kamil --- .github/workflows/goreleaser.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index d7f033ccb5..1785de3574 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -23,6 +23,8 @@ jobs: go-version-file: go.mod - name: Run GoReleaser build uses: goreleaser/goreleaser-action@v6 + env: + SUFFIX: '' with: distribution: goreleaser version: latest @@ -70,9 +72,11 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SUFFIX: '' - name: Update new version in krew-index if: github.repository_owner == 'microsoft' uses: rajatjindal/krew-release-bot@v0.0.47 + release-mcr: name: Release kubectl-retina-mcr runs-on: ubuntu-latest if: github.ref_type == 'tag' From 03fc10b042442a8690171e38df7d82ddfe684d82 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 26 Jun 2025 19:00:59 +0100 Subject: [PATCH 053/448] fix(ci): goreleaser workflow (#1714) # Description This PR fixes goreleaser workflow problem introduced at #1695. `.goreleaser.yaml` * declares 2 builds: kubectl-retina (referring to retina image in ghcr) and kubectl-retina-mcr (referring to retina image in mcr). * declares 2 archives: one with ghcr binary and another with mcr binary. goreleaser workflow, runs `goreleaser` to build and release as declared. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed - ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- .github/workflows/goreleaser.yaml | 49 ++----------------------------- .goreleaser.yaml | 35 ++++++++++++++++++---- 2 files changed, 32 insertions(+), 52 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 1785de3574..aaa54dad0e 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -24,29 +24,7 @@ jobs: - name: Run GoReleaser build uses: goreleaser/goreleaser-action@v6 env: - SUFFIX: '' - with: - distribution: goreleaser - version: latest - args: build --snapshot --clean - build-mcr: - name: Build kubectl-retina-mcr - if: github.ref_type == 'branch' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 0 - - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - name: Run GoReleaser build - uses: goreleaser/goreleaser-action@v6 - env: - AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent - SUFFIX: -mcr + MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent with: distribution: goreleaser version: latest @@ -72,30 +50,7 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SUFFIX: '' + MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent - name: Update new version in krew-index if: github.repository_owner == 'microsoft' uses: rajatjindal/krew-release-bot@v0.0.47 - release-mcr: - name: Release kubectl-retina-mcr - runs-on: ubuntu-latest - if: github.ref_type == 'tag' - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 0 - - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - name: Run GoReleaser release - uses: goreleaser/goreleaser-action@v6 - with: - distribution: goreleaser - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent - SUFFIX: -mcr diff --git a/.goreleaser.yaml b/.goreleaser.yaml index d46c7123cb..e015e7ca7b 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -9,7 +9,8 @@ before: - go mod tidy builds: - - binary: kubectl-retina{{.Env.SUFFIX}}-{{ .Os }}-{{ .Arch }} + - binary: kubectl-retina-{{ .Os }}-{{ .Arch }} + id: retina env: - CGO_ENABLED=0 goarch: @@ -23,14 +24,38 @@ builds: - darwin ldflags: - -X github.com/microsoft/retina/internal/buildinfo.Version=v{{.Version}} - - >- - {{- if index .Env "AGENT_IMAGE_NAME" }} - -X github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName={{.Env.AGENT_IMAGE_NAME}} - {{- end }} + main: cli/main.go + - binary: kubectl-retina-mcr-{{ .Os }}-{{ .Arch }} + id: retina-mcr + env: + - CGO_ENABLED=0 + goarch: + - amd64 + - arm64 + gcflags: + - -dwarflocationlists=true + goos: + - linux + - windows + - darwin + ldflags: + - -X github.com/microsoft/retina/internal/buildinfo.Version=v{{.Version}} + - -X github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName={{.Env.MCR_AGENT_IMAGE_NAME}} main: cli/main.go archives: - name_template: "{{ .Binary }}-v{{ .Version }}" + id: retina-kubectl + ids: + - retina + wrap_in_directory: false + format_overrides: + - goos: windows + formats: [ 'zip' ] + - name_template: "{{ .Binary }}-v{{ .Version }}" + id: retina-kubectl-mcr + ids: + - retina-mcr wrap_in_directory: false format_overrides: - goos: windows From 7f77e1df47f9a446521017e0beaec1fde01a4173 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:47:18 -0400 Subject: [PATCH 054/448] deps: bump go.opentelemetry.io/otel from 1.35.0 to 1.37.0 (#1710) Bumps [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) from 1.35.0 to 1.37.0.
Changelog

Sourced from go.opentelemetry.io/otel's changelog.

[1.37.0/0.59.0/0.13.0] 2025-06-25

Added

  • The go.opentelemetry.io/otel/semconv/v1.33.0 package. The package contains semantic conventions from the v1.33.0 version of the OpenTelemetry Semantic Conventions. See the migration documentation for information on how to upgrade from go.opentelemetry.io/otel/semconv/v1.32.0.(#6799)
  • The go.opentelemetry.io/otel/semconv/v1.34.0 package. The package contains semantic conventions from the v1.34.0 version of the OpenTelemetry Semantic Conventions. (#6812)
  • Add metric's schema URL as otel_scope_schema_url label in go.opentelemetry.io/otel/exporters/prometheus. (#5947)
  • Add metric's scope attributes as otel_scope_[attribute] labels in go.opentelemetry.io/otel/exporters/prometheus. (#5947)
  • Add EventName to EnabledParameters in go.opentelemetry.io/otel/log. (#6825)
  • Add EventName to EnabledParameters in go.opentelemetry.io/otel/sdk/log. (#6825)
  • Changed handling of go.opentelemetry.io/otel/exporters/prometheus metric renaming to add unit suffixes when it doesn't match one of the pre-defined values in the unit suffix map. (#6839)

Changed

  • The semantic conventions have been upgraded from v1.26.0 to v1.34.0 in go.opentelemetry.io/otel/bridge/opentracing. (#6827)
  • The semantic conventions have been upgraded from v1.26.0 to v1.34.0 in go.opentelemetry.io/otel/exporters/zipkin. (#6829)
  • The semantic conventions have been upgraded from v1.26.0 to v1.34.0 in go.opentelemetry.io/otel/metric. (#6832)
  • The semantic conventions have been upgraded from v1.26.0 to v1.34.0 in go.opentelemetry.io/otel/sdk/resource. (#6834)
  • The semantic conventions have been upgraded from v1.26.0 to v1.34.0 in go.opentelemetry.io/otel/sdk/trace. (#6835)
  • The semantic conventions have been upgraded from v1.26.0 to v1.34.0 in go.opentelemetry.io/otel/trace. (#6836)
  • Record.Resource now returns *resource.Resource instead of resource.Resource in go.opentelemetry.io/otel/sdk/log. (#6864)
  • Retry now shows error cause for context timeout in go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc, go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc, go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc, go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp, go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp, go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp. (#6898)

Fixed

  • Stop stripping trailing slashes from configured endpoint URL in go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc. (#6710)
  • Stop stripping trailing slashes from configured endpoint URL in go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp. (#6710)
  • Stop stripping trailing slashes from configured endpoint URL in go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc. (#6710)
  • Stop stripping trailing slashes from configured endpoint URL in go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp. (#6710)
  • Validate exponential histogram scale range for Prometheus compatibility in go.opentelemetry.io/otel/exporters/prometheus. (#6822)
  • Context cancellation during metric pipeline produce does not corrupt data in go.opentelemetry.io/otel/sdk/metric. (#6914)

Removed

  • go.opentelemetry.io/otel/exporters/prometheus no longer exports otel_scope_info metric. (#6770)

[0.12.2] 2025-05-22

Fixed

  • Retract v0.12.0 release of go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc module that contains invalid dependencies. (#6804)
  • Retract v0.12.0 release of go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp module that contains invalid dependencies. (#6804)
  • Retract v0.12.0 release of go.opentelemetry.io/otel/exporters/stdout/stdoutlog module that contains invalid dependencies. (#6804)

[0.12.1] 2025-05-21

Fixes

... (truncated)

Commits
  • 69e8108 Release 1.37.0/0.59.0/0.13.0 (#6925)
  • 67ca271 chore(deps): update golang.org/x/telemetry digest to fef9409 (#6929)
  • b4fad0a chore(deps): update module github.com/grpc-ecosystem/grpc-gateway/v2 to v2.27...
  • 553779c chore: add missing ) in GPG hyperlink (#6928)
  • 351a51f Use existing schema URLs in tests (#6924)
  • a365d85 Add test for logging from a span in the opentracing bridge (#6919)
  • 787518f chore(deps): update google.golang.org/genproto/googleapis/rpc digest to 513f2...
  • fbfb44a chore(deps): update golang.org/x (#6923)
  • 98f7693 chore: flatten bridge/opentracing/internal package (#6916)
  • 1b803e1 fix(deps): update module github.com/prometheus/common to v0.65.0 (#6921)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=go.opentelemetry.io/otel&package-manager=go_modules&previous-version=1.35.0&new-version=1.37.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 261f0e2dff..3924a7af73 100644 --- a/go.mod +++ b/go.mod @@ -230,7 +230,7 @@ require ( require ( github.com/go-chi/chi v4.1.2+incompatible - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.7.0 @@ -301,9 +301,9 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 - go.opentelemetry.io/otel v1.35.0 - go.opentelemetry.io/otel/metric v1.35.0 - go.opentelemetry.io/otel/trace v1.35.0 + go.opentelemetry.io/otel v1.37.0 + go.opentelemetry.io/otel/metric v1.37.0 + go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 google.golang.org/grpc v1.72.0 diff --git a/go.sum b/go.sum index 9ca922e393..7cc6441ae9 100644 --- a/go.sum +++ b/go.sum @@ -598,8 +598,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= @@ -1532,8 +1532,8 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= @@ -1558,16 +1558,16 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgT go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDTe3Y= go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= From 70562b3ca91e2277bc75110183b03dcb63de4519 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:47:37 -0400 Subject: [PATCH 055/448] deps: bump sigstore/cosign-installer from 3.8.2 to 3.9.1 (#1705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.8.2 to 3.9.1.
Release notes

Sourced from sigstore/cosign-installer's releases.

v3.9.1

What's Changed

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v3.9.0...v3.9.1

v3.9.0

What's Changed

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v3...v3.9.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=3.8.2&new-version=3.9.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 6ce60f8894..a8fdd51113 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -27,7 +27,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 8722f4ef5d..cc0d574790 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -32,7 +32,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -78,7 +78,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -124,7 +124,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -169,7 +169,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -212,7 +212,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -260,7 +260,7 @@ jobs: uses: docker/setup-qemu-action@v3 - name: Install Cosign - uses: sigstore/cosign-installer@v3.8.2 + uses: sigstore/cosign-installer@v3.9.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From 9ed820b810a3ae26563ce505fa0e181de5e120e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 09:58:19 -0400 Subject: [PATCH 056/448] deps: bump github.com/cloudflare/circl from 1.3.8 to 1.6.1 in the go_modules group (#1676) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the go_modules group with 1 update: [github.com/cloudflare/circl](https://github.com/cloudflare/circl). Updates `github.com/cloudflare/circl` from 1.3.8 to 1.6.1
Release notes

Sourced from github.com/cloudflare/circl's releases.

CIRCL v1.6.1

  • Fixes some point checks on the FourQ curve.
  • Hybrid KEM fails on low-order points.

What's Changed

Full Changelog: https://github.com/cloudflare/circl/compare/v1.6.0...v1.6.1

CIRCL v1.6.0

New!

What's Changed

New Contributors

Full Changelog: https://github.com/cloudflare/circl/compare/v1.5.0...v1.6.0

CIRCL v1.5.0

New: ML-DSA, Module-Lattice-based Digital Signature Algorithm.

What's Changed

New Contributors

Full Changelog: https://github.com/cloudflare/circl/compare/v1.4.0...v1.5.0

... (truncated)

Commits
  • c6d33e3 Release v1.6.1
  • 0c3868e curve4q: Shared must fail with low order points.
  • 9fd570d curve4q: Test showing DH does not fails on identity point.
  • c988ceb fourq: Correctly unmarshalling point.
  • ef2611d fourq: Test showing point unmarshal fails.
  • 05eba44 fourq: Handle the case of Z=0 for IsOnCurve and IsEqual.
  • eef0878 fourq: Test showing isEqual and IsOnCurve fail.
  • 2298474 goldilocks; Handling points with z=0.
  • 5a940a1 goldilocks: Test for IsEqual must fail with Z=0
  • 48c3b6a ed25519: Fix isEqual to handle points with Z=0.
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/cloudflare/circl&package-manager=go_modules&previous-version=1.3.8&new-version=1.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3924a7af73..eaf35638e7 100644 --- a/go.mod +++ b/go.mod @@ -420,7 +420,7 @@ require ( github.com/chavacava/garif v0.1.0 // indirect github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect github.com/ckaznocha/intrange v0.3.0 // indirect - github.com/cloudflare/circl v1.3.8 // indirect + github.com/cloudflare/circl v1.6.1 // indirect github.com/containerd/console v1.0.4 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect diff --git a/go.sum b/go.sum index 7cc6441ae9..03990f41bc 100644 --- a/go.sum +++ b/go.sum @@ -399,8 +399,8 @@ github.com/cilium/workerpool v1.3.0/go.mod h1:0evs6P39nORTphjRtTtHLXTyCPQUwelXCK github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= -github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= +github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= From 66b19111a024142709bd4f14eafd769109eb32c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 11:49:05 -0400 Subject: [PATCH 057/448] deps: bump golang.org/x/sync from 0.14.0 to 0.15.0 (#1716) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.14.0 to 0.15.0.
Commits
  • 8a14946 errgroup: remove duplicated comment
  • 1869c69 all: replace deprecated ioutil
  • d1ac909 sync/errgroup: PanicError.Error print stack trace
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sync&package-manager=go_modules&previous-version=0.14.0&new-version=0.15.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eaf35638e7..16e78d7fc1 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.14.0 + golang.org/x/sync v0.15.0 golang.org/x/sys v0.33.0 golang.org/x/term v0.32.0 // indirect google.golang.org/protobuf v1.36.6 diff --git a/go.sum b/go.sum index 03990f41bc..94c79e4f44 100644 --- a/go.sum +++ b/go.sum @@ -1707,8 +1707,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 34753fb1e427779a4d1c41d5ed3a2c602ff34b0f Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 27 Jun 2025 13:37:08 -0400 Subject: [PATCH 058/448] chore(site): add build doc step for PR (#1646) # Description Adding the docs build step for every PR ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed https://github.com/microsoft/retina/actions/runs/15351530012/job/43200699404?pr=1646 ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- .github/workflows/docs.yaml | 24 +- docs/08-Contributing/02-development.md | 8 +- site/package-lock.json | 6493 +++++++++++++++--------- site/package.json | 12 +- 4 files changed, 4061 insertions(+), 2476 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 6b35313530..e24a15ecb6 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -3,6 +3,8 @@ name: Build and Deploy Retina.sh on: push: branches: ["main"] + pull_request: + branches: ["main"] workflow_dispatch: merge_group: permissions: @@ -13,17 +15,11 @@ concurrency: group: "pages" cancel-in-progress: false jobs: - deploy: - if: ${{ github.event_name != 'merge_group' }} - environment: - name: retina.sh - url: ${{ steps.deployment.outputs.page_url }} + build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Setup Pages - uses: actions/configure-pages@v5 - uses: actions/setup-node@v4 with: node-version: 20 @@ -31,10 +27,22 @@ jobs: run: | npm install --prefix site/ npm run build --prefix site/ - - name: Upload artifact + - name: Upload build artifact + if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: actions/upload-pages-artifact@v3 with: path: "./site/build" + + deploy: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: build + environment: + name: retina.sh + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Setup Pages + uses: actions/configure-pages@v5 - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 diff --git a/docs/08-Contributing/02-development.md b/docs/08-Contributing/02-development.md index 1ef241a16f..6cfb562653 100644 --- a/docs/08-Contributing/02-development.md +++ b/docs/08-Contributing/02-development.md @@ -16,7 +16,7 @@ Below is a list of required tools and dependencies you need to set up your local - [Docker](https://docs.docker.com/engine/install/) - [Helm](https://helm.sh/docs/intro/install) - jq: `sudo apt install jq` -- If you want to use [ghcr.io](https://github.com/features/packages) as container registry, login following instructions [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic) +- If you want to use [ghcr.io](https://github.com/features/packages) as container registry, login following instructions on [authenticating with a personal access token](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic) Once you have set up your environment fork the repository and create a branch for your changes. @@ -192,8 +192,8 @@ When you're ready to open a pull request, please ensure that your branch is up-t ### Cryptographic Signing of Commits In order to certify the provenance of commits and defend against impersonation, we require that all commits be cryptographically signed. -Documentation for setting up Git and GitHub to sign your commits can be found [here](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). -Additional information about Git's use of GPG can be found [here](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) +Documentation for setting up Git and GitHub to sign your commits can be found in the [GitHub documentation on signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). +Additional information about Git's use of GPG can be found in the [Git documentation on signing your work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) > To configure your Git client to sign commits by default for a local repository, run `git config --add commit.gpgsign true`. @@ -202,7 +202,7 @@ For **GitHub Codespaces** users, please follow [this doc](https://docs.github.co ### Developer Certificate of Origin (DCO) Contributions to Retina must contain a Developer Certificate of Origin within their constituent commits. -This can be accomplished by providing a `-s` flag to `git commit` as documented [here](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s). +This can be accomplished by providing a `-s` flag to `git commit` as documented in the [Git commit documentation](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s). This will add a `Signed-off-by` trailer to your Git commit, affirming your acceptance of the Contributor License Agreement. ### Updating Documentation diff --git a/site/package-lock.json b/site/package-lock.json index 967bc786d3..4eef53f870 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -8,9 +8,9 @@ "name": "retina", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.6.1", - "@docusaurus/plugin-ideal-image": "^3.6.1", - "@docusaurus/preset-classic": "^3.6.1", + "@docusaurus/core": "^3.8.0", + "@docusaurus/plugin-ideal-image": "^3.8.0", + "@docusaurus/preset-classic": "^3.8.0", "@mdx-js/react": "^3.0.0", "@types/react": "^18.3.7", "clsx": "^2.0.0", @@ -22,9 +22,9 @@ "sharp": "^0.33.5" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.5.2", - "@docusaurus/tsconfig": "^3.5.2", - "@docusaurus/types": "^3.5.2", + "@docusaurus/module-type-aliases": "^3.8.0", + "@docusaurus/tsconfig": "^3.8.0", + "@docusaurus/types": "^3.8.0", "css-loader": "^7.1.2", "style-loader": "^4.0.0", "typescript": "^5.6.2" @@ -34,34 +34,34 @@ } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.6.tgz", - "integrity": "sha512-lkDoW4I7h2kKlIgf3pUt1LqvxyYKkVyiypoGLlUnhPSnCpmeOwudM6rNq6YYsCmdQtnDQoW5lUNNuj6ASg3qeg==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.9.tgz", + "integrity": "sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-plugin-algolia-insights": "1.17.6", - "@algolia/autocomplete-shared": "1.17.6" + "@algolia/autocomplete-plugin-algolia-insights": "1.17.9", + "@algolia/autocomplete-shared": "1.17.9" } }, "node_modules/@algolia/autocomplete-plugin-algolia-insights": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.6.tgz", - "integrity": "sha512-17NnaacuFzSWVuZu4NKzVeaFIe9Abpw8w+/gjc7xhZFtqj+GadufzodIdchwiB2eM2cDdiR3icW7gbNTB3K2YA==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.9.tgz", + "integrity": "sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.17.6" + "@algolia/autocomplete-shared": "1.17.9" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.6.tgz", - "integrity": "sha512-Cvg5JENdSCMuClwhJ1ON1/jSuojaYMiUW2KePm18IkdCzPJj/NXojaOxw58RFtQFpJgfVW8h2E8mEoDtLlMdeA==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.9.tgz", + "integrity": "sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.17.6" + "@algolia/autocomplete-shared": "1.17.9" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -69,189 +69,109 @@ } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.6.tgz", - "integrity": "sha512-aq/3V9E00Tw2GC/PqgyPGXtqJUlVc17v4cn1EUhSc+O/4zd04Uwb3UmPm8KDaYQQOrkt1lwvCj2vG2wRE5IKhw==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.9.tgz", + "integrity": "sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ==", "license": "MIT", "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, - "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", - "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", - "license": "MIT", - "dependencies": { - "@algolia/cache-common": "4.24.0" - } - }, - "node_modules/@algolia/cache-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", - "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==", - "license": "MIT" - }, - "node_modules/@algolia/cache-in-memory": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", - "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", - "license": "MIT", - "dependencies": { - "@algolia/cache-common": "4.24.0" - } - }, "node_modules/@algolia/client-abtesting": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.13.0.tgz", - "integrity": "sha512-6CoQjlMi1pmQYMQO8tXfuGxSPf6iKX5FP9MuMe6IWmvC81wwTvOehnwchyBl2wuPVhcw2Ar53K53mQ60DAC64g==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.25.0.tgz", + "integrity": "sha512-1pfQulNUYNf1Tk/svbfjfkLBS36zsuph6m+B6gDkPEivFmso/XnRgwDvjAx80WNtiHnmeNjIXdF7Gos8+OLHqQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/client-account": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", - "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-account/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-account/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, "node_modules/@algolia/client-analytics": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", - "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-analytics/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-analytics/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.25.0.tgz", + "integrity": "sha512-AFbG6VDJX/o2vDd9hqncj1B6B4Tulk61mY0pzTtzKClyTDlNP0xaUiEKhl6E7KO9I/x0FJF5tDCm0Hn6v5x18A==", "license": "MIT", "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.13.0.tgz", - "integrity": "sha512-2SP6bGGWOTN920MLZv8s7yIR3OqY03vEe4U+vb2MGdL8a/8EQznF3L/nTC/rGf/hvEfZlX2tGFxPJaF2waravg==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.25.0.tgz", + "integrity": "sha512-il1zS/+Rc6la6RaCdSZ2YbJnkQC6W1wiBO8+SH+DE6CPMWBU6iDVzH0sCKSAtMWl9WBxoN6MhNjGBnCv9Yy2bA==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.13.0.tgz", - "integrity": "sha512-ldHTe+LVgC6L4Wr6doAQQ7Ku0jAdhaaPg1T+IHzmmiRZb2Uq5OsjW2yC65JifOmzPCiMkIZE2mGRpWgkn5ktlw==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.25.0.tgz", + "integrity": "sha512-blbjrUH1siZNfyCGeq0iLQu00w3a4fBXm0WRIM0V8alcAPo7rWjLbMJMrfBtzL9X5ic6wgxVpDADXduGtdrnkw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", - "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-personalization/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.25.0.tgz", + "integrity": "sha512-aywoEuu1NxChBcHZ1pWaat0Plw7A8jDMwjgRJ00Mcl7wGlwuPt5dJ/LTNcg3McsEUbs2MBNmw0ignXBw9Tbgow==", "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.13.0.tgz", - "integrity": "sha512-pYo0jbLUtPDN1r341UHTaF2fgN5rbaZfDZqjPRKPM+FRlRmxFxqFQm1UUfpkSUWYGn7lECwDpbKYiKUf81MTwA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.25.0.tgz", + "integrity": "sha512-a/W2z6XWKjKjIW1QQQV8PTTj1TXtaKx79uR3NGBdBdGvVdt24KzGAaN7sCr5oP8DW4D3cJt44wp2OY/fZcPAVA==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.13.0.tgz", - "integrity": "sha512-s2ge3uZ6Zg2sPSFibqijgEYsuorxcc8KVHg3I95nOPHvFHdnBtSHymhZvq4sp/fu8ijt/Y8jLwkuqm5myn+2Sg==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.25.0.tgz", + "integrity": "sha512-9rUYcMIBOrCtYiLX49djyzxqdK9Dya/6Z/8sebPn94BekT+KLOpaZCuc6s0Fpfq7nx5J6YY5LIVFQrtioK9u0g==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" }, "engines": { "node": ">= 14.0.0" @@ -264,212 +184,138 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.13.0.tgz", - "integrity": "sha512-fm5LEOe4FPDOc1D+M9stEs8hfcdmbdD+pt9og5shql6ueTZJANDbFoQhDOpiPJizR/ps1GwmjkWfUEywx3sV+Q==", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.25.0.tgz", + "integrity": "sha512-jJeH/Hk+k17Vkokf02lkfYE4A+EJX+UgnMhTLR/Mb+d1ya5WhE+po8p5a/Nxb6lo9OLCRl6w3Hmk1TX1e9gVbQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/logger-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", - "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==", - "license": "MIT" - }, - "node_modules/@algolia/logger-console": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", - "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", - "license": "MIT", - "dependencies": { - "@algolia/logger-common": "4.24.0" - } - }, "node_modules/@algolia/monitoring": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.13.0.tgz", - "integrity": "sha512-e8Hshlnm2G5fapyUgWTBwhJ22yXcnLtPC4LWZKx7KOvv35GcdoHtlUBX94I/sWCJLraUr65JvR8qOo3LXC43dg==", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.25.0.tgz", + "integrity": "sha512-Ls3i1AehJ0C6xaHe7kK9vPmzImOn5zBg7Kzj8tRYIcmCWVyuuFwCIsbuIIz/qzUf1FPSWmw0TZrGeTumk2fqXg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", - "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", - "license": "MIT", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/requester-browser-xhr": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", - "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/requester-node-http": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", - "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.25.0.tgz", + "integrity": "sha512-79sMdHpiRLXVxSjgw7Pt4R1aNUHxFLHiaTDnN2MQjHwJ1+o3wSseb55T9VXU4kqy3m7TUme3pyRhLk5ip/S4Mw==", "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.24.0" + "@algolia/client-common": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.13.0.tgz", - "integrity": "sha512-NV6oSCt5lFuzfsVQoSBpewEWf/h4ySr7pv2bfwu9yF/jc/g39pig8+YpuqsxlRWBm/lTGVA2V0Ai9ySwrNumIA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.25.0.tgz", + "integrity": "sha512-JLaF23p1SOPBmfEqozUAgKHQrGl3z/Z5RHbggBu6s07QqXXcazEsub5VLonCxGVqTv6a61AAPr8J1G5HgGGjEw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0" + "@algolia/client-common": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/requester-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", - "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==", - "license": "MIT" - }, "node_modules/@algolia/requester-fetch": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.13.0.tgz", - "integrity": "sha512-094bK4rumf+rXJazxv3mq6eKRM0ep5AxIo8T0YmOdldswQt79apeufFiPLN19nHEWH22xR2FelimD+T/wRSP+Q==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.25.0.tgz", + "integrity": "sha512-rtzXwqzFi1edkOF6sXxq+HhmRKDy7tz84u0o5t1fXwz0cwx+cjpmxu/6OQKTdOJFS92JUYHsG51Iunie7xbqfQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0" + "@algolia/client-common": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.13.0.tgz", - "integrity": "sha512-JY5xhEYMgki53Wm+A6R2jUpOUdD0zZnBq+PC5R1TGMNOYL1s6JjDrJeMsvaI2YWxYMUSoCnRoltN/yf9RI8n3A==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.25.0.tgz", + "integrity": "sha512-ZO0UKvDyEFvyeJQX0gmZDQEvhLZ2X10K+ps6hViMo1HgE2V8em00SwNsQ+7E/52a+YiBkVWX61pJJJE44juDMQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0" + "@algolia/client-common": "5.25.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@algolia/transporter": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", - "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", - "license": "MIT", - "dependencies": { - "@algolia/cache-common": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/requester-common": "4.24.0" - } - }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz", + "integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.4", + "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -488,18 +334,19 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", + "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.27.3", + "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -509,38 +356,25 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", - "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/types": "^7.27.3" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -559,17 +393,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", - "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", + "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.25.9", + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.27.1", "semver": "^6.3.1" }, "engines": { @@ -589,13 +423,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", - "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", + "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.1.1", + "@babel/helper-annotate-as-pure": "^7.27.1", + "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, "engines": { @@ -609,14 +443,15 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", + "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -630,40 +465,40 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -673,35 +508,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -711,14 +546,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", - "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -727,93 +562,80 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", - "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", + "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", "license": "MIT", "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", - "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz", + "integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==", "license": "MIT", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", - "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", + "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.10" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -823,13 +645,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", + "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -839,12 +661,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -854,12 +676,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -869,14 +691,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -886,13 +708,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", + "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -905,6 +727,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", "engines": { "node": ">=6.9.0" }, @@ -916,6 +739,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -924,12 +748,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", - "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -939,12 +763,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -954,12 +778,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -969,12 +793,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -987,6 +811,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -999,12 +824,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1014,14 +839,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", - "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", + "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1031,14 +856,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1048,12 +873,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", - "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1063,12 +888,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", - "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz", + "integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1078,13 +903,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", - "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1094,13 +919,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", - "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", + "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1110,16 +935,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", + "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.27.1", "globals": "^11.1.0" }, "engines": { @@ -1130,13 +955,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1146,12 +971,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.3.tgz", + "integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1161,13 +986,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", - "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1177,12 +1002,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", - "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1192,13 +1017,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1208,12 +1033,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", - "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1223,13 +1048,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", - "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", + "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1239,12 +1063,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", - "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1254,13 +1078,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", - "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1270,14 +1094,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1287,12 +1111,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", - "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1302,12 +1126,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1317,12 +1141,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", - "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", + "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1332,12 +1156,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", - "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1347,13 +1171,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", - "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1363,14 +1187,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", - "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-simple-access": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1380,15 +1203,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", + "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1398,13 +1221,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", - "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1414,13 +1237,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1430,12 +1253,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", - "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1445,12 +1268,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", - "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1460,12 +1283,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", - "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1475,14 +1298,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", - "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.3.tgz", + "integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9" + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.27.3", + "@babel/plugin-transform-parameters": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1492,13 +1316,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", - "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1508,12 +1332,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", - "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1523,13 +1347,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", + "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1539,12 +1363,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", + "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1554,13 +1378,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", - "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1570,14 +1394,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", - "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1587,12 +1411,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", - "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1602,12 +1426,12 @@ } }, "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", - "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.27.1.tgz", + "integrity": "sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1617,12 +1441,12 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", - "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz", + "integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1632,16 +1456,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", - "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", + "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1651,12 +1475,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", - "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.25.9" + "@babel/plugin-transform-react-jsx": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1666,13 +1490,13 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", - "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1682,13 +1506,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", - "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.4.tgz", + "integrity": "sha512-Glp/0n8xuj+E1588otw5rjJkTXfzW7FjH3IIUrfqiZOPQCd2vbg8e+DQE8jK9g4V5/zrxFW+D9WM9gboRPELpQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "regenerator-transform": "^0.15.2" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1698,13 +1521,13 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", - "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1714,12 +1537,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", - "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1729,15 +1552,15 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", - "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.4.tgz", + "integrity": "sha512-D68nR5zxU64EUzV8i7T3R5XP0Xhrou/amNnddsRQssx6GrTLdZl1rLxyjtVZBd+v/NVX4AbTPOB5aU8thAZV1A==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, @@ -1758,12 +1581,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1773,13 +1596,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1789,12 +1612,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1804,12 +1627,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", - "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1819,12 +1642,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", - "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1834,16 +1657,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", - "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.1.tgz", + "integrity": "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1853,12 +1676,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", - "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1868,13 +1691,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", - "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1884,13 +1707,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1900,13 +1723,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", - "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1916,79 +1739,79 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", - "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", + "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.25.9", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.25.9", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.25.9", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.25.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.25.9", - "@babel/plugin-transform-typeof-symbol": "^7.25.9", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.27.1", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.27.1", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.27.1", + "@babel/plugin-transform-classes": "^7.27.1", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.27.2", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.1", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.27.1", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", + "core-js-compat": "^3.40.0", "semver": "^6.3.1" }, "engines": { @@ -2002,6 +1825,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2010,6 +1834,7 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2020,17 +1845,17 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz", - "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz", + "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-transform-react-display-name": "^7.25.9", - "@babel/plugin-transform-react-jsx": "^7.25.9", - "@babel/plugin-transform-react-jsx-development": "^7.25.9", - "@babel/plugin-transform-react-pure-annotations": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.27.1", + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2040,16 +1865,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", - "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", + "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-typescript": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2071,43 +1896,42 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.10.tgz", - "integrity": "sha512-uITFQYO68pMEYR46AHgQoyBg7KPPJDAbGn4jUTIRgCFJIp88MIBUianVOplhZDEec07bp9zIyr4Kp0FCyQzmWg==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.4.tgz", + "integrity": "sha512-H7QhL0ucCGOObsUETNbB2PuzF4gAvN8p32P6r91bX7M/hk4bx+3yz2hTwHL9d/Efzwu1upeb4/cd7oSxCzup3w==", "license": "MIT", "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" + "core-js-pure": "^3.30.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2116,13 +1940,13 @@ } }, "node_modules/@babel/types": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", - "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", + "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2137,161 +1961,1221 @@ "node": ">=0.1.90" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.5.tgz", + "integrity": "sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@docsearch/css": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.7.0.tgz", - "integrity": "sha512-1OorbTwi1eeDmr0v5t+ckSRlt1zM5GHjm92iIl3kUu7im3GHuP+csf6E0WBg8pdXQczTWP9J9+o9n+Vg6DH5cQ==", - "license": "MIT" + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } }, - "node_modules/@docsearch/react": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.7.0.tgz", - "integrity": "sha512-8e6tdDfkYoxafEEPuX5eE1h9cTkLvhe4KgoFkO5JCddXSQONnN1FHcDZRI4r8894eMpbYq6rdJF0dVYh8ikwNQ==", + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@algolia/autocomplete-core": "1.17.6", - "@algolia/autocomplete-preset-algolia": "1.17.6", - "@docsearch/css": "3.7.0", - "algoliasearch": "^5.12.0" + "engines": { + "node": ">=18" }, "peerDependencies": { - "@types/react": ">= 16.8.0 < 19.0.0", - "react": ">= 16.8.0 < 19.0.0", - "react-dom": ">= 16.8.0 < 19.0.0", - "search-insights": ">= 1 < 3" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "search-insights": { - "optional": true - } + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@docsearch/react/node_modules/@algolia/client-analytics": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.13.0.tgz", - "integrity": "sha512-pS3qyXiWTwKnrt/jE79fqkNqZp7kjsFNlJDcBGkSWid74DNc6DmArlkvPqyLxnoaYGjUGACT6g56n7E3mVV2TA==", + "node_modules/@csstools/css-color-parser": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", + "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.4" }, "engines": { - "node": ">= 14.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@docsearch/react/node_modules/@algolia/client-personalization": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.13.0.tgz", - "integrity": "sha512-RnCfOSN4OUJDuMNHFca2M8lY64Tmw0kQOZikge4TknTqHmlbKJb8IbJE7Rol79Z80W2Y+B1ydcjV7DPje4GMRA==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" - }, "engines": { - "node": ">= 14.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@docsearch/react/node_modules/@algolia/recommend": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.13.0.tgz", - "integrity": "sha512-53/wW96oaj1FKMzGdFcZ/epygfTppLDUvgI1thLkd475EtVZCH3ZZVUNCEvf1AtnNyH1RnItkFzX8ayWCpx2PQ==", + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" - }, "engines": { - "node": ">= 14.0.0" + "node": ">=18" } }, - "node_modules/@docsearch/react/node_modules/algoliasearch": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.13.0.tgz", - "integrity": "sha512-04lyQX3Ev/oLYQx+aagamQDXvkUUfX1mwrLrus15+9fNaYj28GDxxEzbwaRfvmHFcZyoxvup7mMtDTTw8SrTEQ==", + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@algolia/client-abtesting": "5.13.0", - "@algolia/client-analytics": "5.13.0", - "@algolia/client-common": "5.13.0", - "@algolia/client-insights": "5.13.0", - "@algolia/client-personalization": "5.13.0", - "@algolia/client-query-suggestions": "5.13.0", - "@algolia/client-search": "5.13.0", - "@algolia/ingestion": "1.13.0", - "@algolia/monitoring": "1.13.0", - "@algolia/recommend": "5.13.0", - "@algolia/requester-browser-xhr": "5.13.0", - "@algolia/requester-fetch": "5.13.0", - "@algolia/requester-node-http": "5.13.0" - }, "engines": { - "node": ">= 14.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@docusaurus/babel": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.6.1.tgz", - "integrity": "sha512-JcKaunW8Ml2nTnfnvFc55T00Y+aCpNWnf1KY/gG+wWxHYDH0IdXOOz+k6NAlEAerW8+VYLfUqRIqHZ7N/DVXvQ==", - "license": "MIT", + "node_modules/@csstools/postcss-cascade-layers": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.1.tgz", + "integrity": "sha512-XOfhI7GShVcKiKwmPAnWSqd2tBR0uxt+runAxttbSp/LY2U16yAVPmAf7e9q4JJ0d+xMNmpwNDLBXnmRCl3HMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/runtime-corejs3": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.6.1", - "@docusaurus/utils": "3.6.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": ">=18.0" - } - }, + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.10.tgz", + "integrity": "sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-function": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.10.tgz", + "integrity": "sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.0.tgz", + "integrity": "sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-content-alt-text": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.6.tgz", + "integrity": "sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-exponential-functions": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.9.tgz", + "integrity": "sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-4.0.0.tgz", + "integrity": "sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gamut-mapping": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.10.tgz", + "integrity": "sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gradients-interpolation-method": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.10.tgz", + "integrity": "sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.10.tgz", + "integrity": "sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.2.tgz", + "integrity": "sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-initial": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-2.0.1.tgz", + "integrity": "sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz", + "integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-light-dark-function": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.9.tgz", + "integrity": "sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-3.0.0.tgz", + "integrity": "sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overflow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-2.0.0.tgz", + "integrity": "sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overscroll-behavior": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-2.0.0.tgz", + "integrity": "sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-resize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-3.0.0.tgz", + "integrity": "sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.4.tgz", + "integrity": "sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-minmax": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.9.tgz", + "integrity": "sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.5.tgz", + "integrity": "sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-4.0.0.tgz", + "integrity": "sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz", + "integrity": "sha512-HlEoG0IDRoHXzXnkV4in47dzsxdsjdz6+j7MLjaACABX2NfvjFS6XVAnpaDyGesz9gK2SC7MbNwdCHusObKJ9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.10.tgz", + "integrity": "sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.1.0.tgz", + "integrity": "sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-random-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-2.0.1.tgz", + "integrity": "sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-relative-color-syntax": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.10.tgz", + "integrity": "sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-4.0.1.tgz", + "integrity": "sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-sign-functions": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.4.tgz", + "integrity": "sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.9.tgz", + "integrity": "sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz", + "integrity": "sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.9.tgz", + "integrity": "sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-4.0.0.tgz", + "integrity": "sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/utilities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", + "integrity": "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.9.0.tgz", + "integrity": "sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA==", + "license": "MIT" + }, + "node_modules/@docsearch/react": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.9.0.tgz", + "integrity": "sha512-mb5FOZYZIkRQ6s/NWnM98k879vu5pscWqTLubLFBO87igYYT4VzVazh4h5o/zCvTIZgEt3PvsCOMOswOUo9yHQ==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.9", + "@algolia/autocomplete-preset-algolia": "1.17.9", + "@docsearch/css": "3.9.0", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 20.0.0", + "react": ">= 16.8.0 < 20.0.0", + "react-dom": ">= 16.8.0 < 20.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docusaurus/babel": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.0.tgz", + "integrity": "sha512-9EJwSgS6TgB8IzGk1L8XddJLhZod8fXT4ULYMx6SKqyCBqCFpVCEjR/hNXXhnmtVM2irDuzYoVLGWv7srG/VOA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/runtime-corejs3": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.8.0", + "@docusaurus/utils": "3.8.0", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, "node_modules/@docusaurus/bundler": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.6.1.tgz", - "integrity": "sha512-vHSEx8Ku9x/gfIC6k4xb8J2nTxagLia0KvZkPZhxfkD1+n8i+Dj4BZPWTmv+kCA17RbgAvECG0XRZ0/ZEspQBQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.0.tgz", + "integrity": "sha512-Rq4Z/MSeAHjVzBLirLeMcjLIAQy92pF1OI+2rmt18fSlMARfTGLWRE8Vb+ljQPTOSfJxwDYSzsK6i7XloD2rNA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.6.1", - "@docusaurus/cssnano-preset": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", - "autoprefixer": "^10.4.14", + "@docusaurus/babel": "3.8.0", + "@docusaurus/cssnano-preset": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", "babel-loader": "^9.2.1", "clean-css": "^5.3.2", "copy-webpack-plugin": "^11.0.0", @@ -2304,7 +3188,7 @@ "null-loader": "^4.0.1", "postcss": "^8.4.26", "postcss-loader": "^7.3.3", - "react-dev-utils": "^12.0.1", + "postcss-preset-env": "^10.1.0", "terser-webpack-plugin": "^5.3.9", "tslib": "^2.6.0", "url-loader": "^4.1.1", @@ -2359,18 +3243,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.6.1.tgz", - "integrity": "sha512-cDKxPihiM2z7G+4QtpTczS7uxNfNG6naSqM65OmAJET0CFRHbc9mDlLFtQF0lsVES91SHqfcGaaLZmi2FjdwWA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.0.tgz", + "integrity": "sha512-c7u6zFELmSGPEP9WSubhVDjgnpiHgDqMh1qVdCB7rTflh4Jx0msTYmMiO91Ez0KtHj4sIsDsASnjwfJ2IZp3Vw==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.6.1", - "@docusaurus/bundler": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/mdx-loader": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/babel": "3.8.0", + "@docusaurus/bundler": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/mdx-loader": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -2378,29 +3262,28 @@ "combine-promises": "^1.1.0", "commander": "^5.1.0", "core-js": "^3.31.1", - "del": "^6.1.1", "detect-port": "^1.5.1", "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", + "execa": "5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", "leven": "^3.1.0", "lodash": "^4.17.21", + "open": "^8.4.0", "p-map": "^4.0.0", "prompts": "^2.4.2", - "react-dev-utils": "^12.0.1", - "react-helmet-async": "^1.3.0", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", "react-loadable-ssr-addon-v5-slorber": "^1.0.1", "react-router": "^5.3.4", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.4", - "rtl-detect": "^1.0.4", "semver": "^7.5.4", "serve-handler": "^6.1.6", - "shelljs": "^0.8.5", + "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", "webpack": "^5.95.0", @@ -2416,8 +3299,8 @@ }, "peerDependencies": { "@mdx-js/react": "^3.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/core/node_modules/webpack-merge": { @@ -2435,9 +3318,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.6.1.tgz", - "integrity": "sha512-ZxYUmNeyQHW2w4/PJ7d07jQDuxzmKr9uPAQ6IVe5dTkeIeV0mDBB3jOLeJkNoI42Ru9JKEqQ9aVDtM9ct6QHnw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.0.tgz", + "integrity": "sha512-UJ4hAS2T0R4WNy+phwVff2Q0L5+RXW9cwlH6AEphHR5qw3m/yacfWcSK7ort2pMMbDn8uGrD38BTm4oLkuuNoQ==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", @@ -2450,9 +3333,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.6.1.tgz", - "integrity": "sha512-OvetI/nnOMBSqCkUzKAQhnIjhxduECK4qTu3tq/8/h/qqvLsvKURojm04WPE54L+Uy+UXMas0hnbBJd8zDlEOw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.0.tgz", + "integrity": "sha512-7eEMaFIam5Q+v8XwGqF/n0ZoCld4hV4eCCgQkfcN9Mq5inoZa6PHHW9Wu6lmgzoK5Kx3keEeABcO2SxwraoPDQ==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -2463,12 +3346,12 @@ } }, "node_modules/@docusaurus/lqip-loader": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.6.1.tgz", - "integrity": "sha512-H/VVvnvFupFhQ81FuTyA/XHxEZPKh99T6Wg6KgN+/yvcn7869RdgrlDhKDnXZ7j2u80eFsVNjAcPfW1cSAtK6A==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.8.0.tgz", + "integrity": "sha512-8QYQsc5lgw7JdMABDEN6F9FE3JVDeRL+uDEfdwukYVggLI2sVfkfqWGHjH4r4szv02/z7Bv+hUn2pMuWqJm/cw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.6.1", + "@docusaurus/logger": "3.8.0", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", @@ -2502,21 +3385,21 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.6.1.tgz", - "integrity": "sha512-KPIsYi0S3X3/rNrW3V1fgOu5t6ahYWc31zTHHod8pacFxdmk9Uf6uuw+Jd6Cly1ilgal+41Ku+s0gmMuqKqiqg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.0.tgz", + "integrity": "sha512-mDPSzssRnpjSdCGuv7z2EIAnPS1MHuZGTaRLwPn4oQwszu4afjWZ/60sfKjTnjBjI8Vl4OgJl2vMmfmiNDX4Ng==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/logger": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", "estree-util-value-to-estree": "^3.0.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "image-size": "^1.0.2", + "image-size": "^2.0.2", "mdast-util-mdx": "^3.0.0", "mdast-util-to-string": "^4.0.0", "rehype-raw": "^7.0.0", @@ -2536,22 +3419,22 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.6.1.tgz", - "integrity": "sha512-J+q1jgm7TnEfVIUZImSFeLA1rghb6nwtoB9siHdcgKpDqFJ9/S7xhQL2aEKE7iZMZYzpu+2F390E9A7GkdEJNA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.0.tgz", + "integrity": "sha512-/uMb4Ipt5J/QnD13MpnoC/A4EYAe6DKNWqTWLlGrqsPJwJv73vSwkA25xnYunwfqWk0FlUQfGv/Swdh5eCCg7g==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.6.1", + "@docusaurus/types": "3.8.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", "@types/react-router-dom": "*", - "react-helmet-async": "*", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, "peerDependencies": { @@ -2560,24 +3443,24 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.6.1.tgz", - "integrity": "sha512-FUmsn3xg/XD/K/4FQd8XHrs92aQdZO5LUtpHnRvO1/6DY87SMz6B6ERAN9IGQQld//M2/LVTHkZy8oVhQZQHIQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/mdx-loader": "3.6.1", - "@docusaurus/theme-common": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.8.0.tgz", + "integrity": "sha512-0SlOTd9R55WEr1GgIXu+hhTT0hzARYx3zIScA5IzpdekZQesI/hKEa5LPHBd415fLkWMjdD59TaW/3qQKpJ0Lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/mdx-loader": "3.8.0", + "@docusaurus/theme-common": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21", - "reading-time": "^1.5.0", + "schema-dts": "^1.1.2", "srcset": "^4.0.0", "tslib": "^2.6.0", "unist-util-visit": "^5.0.0", @@ -2589,30 +3472,31 @@ }, "peerDependencies": { "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.6.1.tgz", - "integrity": "sha512-Uq8kyn5DYCDmkUlB9sWChhWghS4lUFNiQU+RXcAXJ3qCVXsBpPsh6RF+npQG1N+j4wAbjydM1iLLJJzp+x3eMQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/mdx-loader": "3.6.1", - "@docusaurus/module-type-aliases": "3.6.1", - "@docusaurus/theme-common": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.0.tgz", + "integrity": "sha512-fRDMFLbUN6eVRXcjP8s3Y7HpAt9pzPYh1F/7KKXOCxvJhjjCtbon4VJW0WndEPInVz4t8QUXn5QZkU2tGVCE2g==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/mdx-loader": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.0", + "@docusaurus/theme-common": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", "js-yaml": "^4.1.0", "lodash": "^4.17.21", + "schema-dts": "^1.1.2", "tslib": "^2.6.0", "utility-types": "^3.10.0", "webpack": "^5.88.1" @@ -2621,21 +3505,21 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.6.1.tgz", - "integrity": "sha512-TZtL+2zq20gqGalzoIT2rEF1T4YCZ26jTvlCJXs78+incIajfdHtmdOq7rQW0oV7oqTjpGllbp788nY/vY9jgw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.8.0.tgz", + "integrity": "sha512-39EDx2y1GA0Pxfion5tQZLNJxL4gq6susd1xzetVBjVIQtwpCdyloOfQBAgX0FylqQxfJrYqL0DIUuq7rd7uBw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/mdx-loader": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/mdx-loader": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2644,59 +3528,74 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.8.0.tgz", + "integrity": "sha512-/VBTNymPIxQB8oA3ZQ4GFFRYdH4ZxDRRBECxyjRyv486mfUPXfcdk+im4S5mKWa6EK2JzBz95IH/Wu0qQgJ5yQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.6.1.tgz", - "integrity": "sha512-DeKPZtoVExDSYCbzoz7y5Dhc6+YPqRWfVGwEEUyKopSyQYefp0OV8hvASmbJCn2WyThRgspOUhog3FSEhz+agw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.8.0.tgz", + "integrity": "sha512-teonJvJsDB9o2OnG6ifbhblg/PXzZvpUKHFgD8dOL1UJ58u0lk8o0ZOkvaYEBa9nDgqzoWrRk9w+e3qaG2mOhQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", "fs-extra": "^11.1.1", - "react-json-view-lite": "^1.2.0", + "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" }, "engines": { "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.6.1.tgz", - "integrity": "sha512-ZEoERiDHxSfhaEeT35ukQ892NzGHWiUvfxUsnPiRuGEhMoQlxMSp60shBuSZ1sUKuZlndoEl5qAXJg09Wls/Sg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.8.0.tgz", + "integrity": "sha512-aKKa7Q8+3xRSRESipNvlFgNp3FNPELKhuo48Cg/svQbGNwidSHbZT03JqbW4cBaQnyyVchO1ttk+kJ5VC9Gx0w==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "tslib": "^2.6.0" }, "engines": { "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.6.1.tgz", - "integrity": "sha512-u/E9vXUsZxYaV6Brvfee8NiH/iR0cMml9P/ifz4EpH/Jfxdbw8rbCT0Nm/h7EFgEY48Uqkl5huSbIvFB9n8aTQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.8.0.tgz", + "integrity": "sha512-ugQYMGF4BjbAW/JIBtVcp+9eZEgT9HRdvdcDudl5rywNPBA0lct+lXMG3r17s02rrhInMpjMahN3Yc9Cb3H5/g==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -2704,43 +3603,41 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.6.1.tgz", - "integrity": "sha512-By+NKkGYV8tSo8/RyS1OXikOtqsko5jJZ/uioJfBjsBGgSbiMJ+Y/HogFBke0mgSvf7NPGKZTbYm5+FJ8YUtPQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.8.0.tgz", + "integrity": "sha512-9juRWxbwZD3SV02Jd9QB6yeN7eu+7T4zB0bvJLcVQwi+am51wAxn2CwbdL0YCCX+9OfiXbADE8D8Q65Hbopu/w==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "tslib": "^2.6.0" }, "engines": { "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.6.1.tgz", - "integrity": "sha512-hiGRPPlsM02aEOPlQc9rVnrckbVR6HswG7yDpZOtBEhw+ysXFsl/8gzAxFBL4ogKjN28WrlMCn/6IIkxY/EyOQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.8.0.tgz", + "integrity": "sha512-DPjOP+IceHDaGdQNowW2zQmDJF5keQgQZr58p2rY82f5W/SwcNwpPuLKzzqfym4xJTo8EtqpdeqWnY63kzUQKQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/lqip-loader": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/lqip-loader": "3.8.0", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", - "@slorber/react-ideal-image": "^0.0.12", - "react-waypoint": "^10.3.0", + "@docusaurus/theme-translations": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "sharp": "^0.32.3", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2750,8 +3647,8 @@ }, "peerDependencies": { "jimp": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "jimp": { @@ -2782,17 +3679,17 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.6.1.tgz", - "integrity": "sha512-i8R/GTKew4Cufb+7YQTwfPcNOhKTJzZ1VZ5OqQwI9c3pZK2TltQyhqKDVN94KCTbSSKvOYYytYfRAB2uPnH1/A==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.8.0.tgz", + "integrity": "sha512-fGpOIyJvNiuAb90nSJ2Gfy/hUOaDu6826e5w5UxPmbpCIc7KlBHNAZ5g4L4ZuHhc4hdfq4mzVBsQSnne+8Ze1g==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "@docusaurus/core": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -2801,36 +3698,61 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/preset-classic": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.6.1.tgz", - "integrity": "sha512-b90Y1XRH9e+oa/E3NmiFEFOwgYUd+knFcZUy81nM3FJs038WbEA0T55NQsuPW0s7nOsCShQ7dVFyKxV+Wp31Nw==", + "node_modules/@docusaurus/plugin-svgr": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.8.0.tgz", + "integrity": "sha512-kEDyry+4OMz6BWLG/lEqrNsL/w818bywK70N1gytViw4m9iAmoxCUT7Ri9Dgs7xUdzCHJ3OujolEmD88Wy44OA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/plugin-content-blog": "3.6.1", - "@docusaurus/plugin-content-docs": "3.6.1", - "@docusaurus/plugin-content-pages": "3.6.1", - "@docusaurus/plugin-debug": "3.6.1", - "@docusaurus/plugin-google-analytics": "3.6.1", - "@docusaurus/plugin-google-gtag": "3.6.1", - "@docusaurus/plugin-google-tag-manager": "3.6.1", - "@docusaurus/plugin-sitemap": "3.6.1", - "@docusaurus/theme-classic": "3.6.1", - "@docusaurus/theme-common": "3.6.1", - "@docusaurus/theme-search-algolia": "3.6.1", - "@docusaurus/types": "3.6.1" + "@docusaurus/core": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.8.0.tgz", + "integrity": "sha512-qOu6tQDOWv+rpTlKu+eJATCJVGnABpRCPuqf7LbEaQ1mNY//N/P8cHQwkpAU+aweQfarcZ0XfwCqRHJfjeSV/g==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.0", + "@docusaurus/plugin-content-blog": "3.8.0", + "@docusaurus/plugin-content-docs": "3.8.0", + "@docusaurus/plugin-content-pages": "3.8.0", + "@docusaurus/plugin-css-cascade-layers": "3.8.0", + "@docusaurus/plugin-debug": "3.8.0", + "@docusaurus/plugin-google-analytics": "3.8.0", + "@docusaurus/plugin-google-gtag": "3.8.0", + "@docusaurus/plugin-google-tag-manager": "3.8.0", + "@docusaurus/plugin-sitemap": "3.8.0", + "@docusaurus/plugin-svgr": "3.8.0", + "@docusaurus/theme-classic": "3.8.0", + "@docusaurus/theme-common": "3.8.0", + "@docusaurus/theme-search-algolia": "3.8.0", + "@docusaurus/types": "3.8.0" }, "engines": { "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/responsive-loader": { @@ -2857,24 +3779,24 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.6.1.tgz", - "integrity": "sha512-5lVUmIXk7zp+n9Ki2lYWrmhbd6mssOlKCnnDJvY4QDi3EgjRisIu5g4yKXoWTIbiqE7m7q/dS9cbeShEtfkKng==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/mdx-loader": "3.6.1", - "@docusaurus/module-type-aliases": "3.6.1", - "@docusaurus/plugin-content-blog": "3.6.1", - "@docusaurus/plugin-content-docs": "3.6.1", - "@docusaurus/plugin-content-pages": "3.6.1", - "@docusaurus/theme-common": "3.6.1", - "@docusaurus/theme-translations": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.8.0.tgz", + "integrity": "sha512-nQWFiD5ZjoT76OaELt2n33P3WVuuCz8Dt5KFRP2fCBo2r9JCLsp2GJjZpnaG24LZ5/arRjv4VqWKgpK0/YLt7g==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/mdx-loader": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.0", + "@docusaurus/plugin-content-blog": "3.8.0", + "@docusaurus/plugin-content-docs": "3.8.0", + "@docusaurus/plugin-content-pages": "3.8.0", + "@docusaurus/theme-common": "3.8.0", + "@docusaurus/theme-translations": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", @@ -2893,20 +3815,20 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/theme-common": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.6.1.tgz", - "integrity": "sha512-18iEYNpMvarGfq9gVRpGowSZD24vZ39Iz4acqaj64180i54V9el8tVnhNr/wRvrUm1FY30A1NHLqnMnDz4rYEQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.0.tgz", + "integrity": "sha512-YqV2vAWpXGLA+A3PMLrOMtqgTHJLDcT+1Caa6RF7N4/IWgrevy5diY8oIHFkXR/eybjcrFFjUPrHif8gSGs3Tw==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.6.1", - "@docusaurus/module-type-aliases": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", + "@docusaurus/mdx-loader": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2921,26 +3843,26 @@ }, "peerDependencies": { "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.6.1.tgz", - "integrity": "sha512-BjmuiFRpQP1WEm8Mzu1Bb0Wdas6G65VHXDDNr7XTKgbstxalE6vuxt0ioXTDFS2YVep5748aVhKvnxR9gm2Liw==", - "license": "MIT", - "dependencies": { - "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.6.1", - "@docusaurus/logger": "3.6.1", - "@docusaurus/plugin-content-docs": "3.6.1", - "@docusaurus/theme-common": "3.6.1", - "@docusaurus/theme-translations": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-validation": "3.6.1", - "algoliasearch": "^4.18.0", - "algoliasearch-helper": "^3.13.3", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.0.tgz", + "integrity": "sha512-GBZ5UOcPgiu6nUw153+0+PNWvFKweSnvKIL6Rp04H9olKb475jfKjAwCCtju5D2xs5qXHvCMvzWOg5o9f6DtuQ==", + "license": "MIT", + "dependencies": { + "@docsearch/react": "^3.9.0", + "@docusaurus/core": "3.8.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/plugin-content-docs": "3.8.0", + "@docusaurus/theme-common": "3.8.0", + "@docusaurus/theme-translations": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-validation": "3.8.0", + "algoliasearch": "^5.17.1", + "algoliasearch-helper": "^3.22.6", "clsx": "^2.0.0", "eta": "^2.2.0", "fs-extra": "^11.1.1", @@ -2952,14 +3874,14 @@ "node": ">=18.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.6.1.tgz", - "integrity": "sha512-bNm5G6sueUezvyhsBegA1wwM38yW0BnqpZTE9KHO2yKnkERNMaV5x/yPJ/DNCOHjJtCcJ5Uz55g2AS75Go31xA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.0.tgz", + "integrity": "sha512-1DTy/snHicgkCkryWq54fZvsAglTdjTx4qjOXgqnXJ+DIty1B+aPQrAVUu8LiM+6BiILfmNxYsxhKTj+BS3PZg==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", @@ -2970,15 +3892,16 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.5.2.tgz", - "integrity": "sha512-rQ7toURCFnWAIn8ubcquDs0ewhPwviMzxh6WpRjBW7sJVCXb6yzwUaY3HMNa0VXCFw+qkIbFywrMTf+Pb4uHWQ==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.8.0.tgz", + "integrity": "sha512-utLl48nNjSYBoq47RKukZ9fPLEX3nJWThzrujb0ndQQ1jc/gh4RhTRaAqItH9nImnsgGKmLMnyoMBpfGmoop+w==", + "dev": true, + "license": "MIT" }, "node_modules/@docusaurus/types": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.6.1.tgz", - "integrity": "sha512-hCB1hj9DYutVYBisnPNobz9SzEmCcf1EetJv09O49Cov3BqOkm+vnnjB3d957YJMtpLGQoKBeN/FF1DZ830JwQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.0.tgz", + "integrity": "sha512-RDEClpwNxZq02c+JlaKLWoS13qwWhjcNsi2wG1UpzmEnuti/z1Wx4SGpqbUqRPNSd8QWWePR8Cb7DvG0VN/TtA==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", @@ -2986,27 +3909,27 @@ "@types/react": "*", "commander": "^5.1.0", "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "utility-types": "^3.10.0", "webpack": "^5.95.0", "webpack-merge": "^5.9.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/utils": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.6.1.tgz", - "integrity": "sha512-nS3WCvepwrnBEgSG5vQu40XG95lC9Jeh/odV5u5IhU1eQFEGDst9xBi6IK5yZdsGvbuaXBZLZtOqWYtuuFa/rQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.0.tgz", + "integrity": "sha512-2wvtG28ALCN/A1WCSLxPASFBFzXCnP0YKCAFIPcvEb6imNu1wg7ni/Svcp71b3Z2FaOFFIv4Hq+j4gD7gA0yfQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.6.1", - "@docusaurus/types": "3.6.1", - "@docusaurus/utils-common": "3.6.1", - "@svgr/webpack": "^8.1.0", + "@docusaurus/logger": "3.8.0", + "@docusaurus/types": "3.8.0", + "@docusaurus/utils-common": "3.8.0", "escape-string-regexp": "^4.0.0", + "execa": "5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "github-slugger": "^1.5.0", @@ -3016,9 +3939,9 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", "tslib": "^2.6.0", "url-loader": "^4.1.1", "utility-types": "^3.10.0", @@ -3029,12 +3952,12 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.6.1.tgz", - "integrity": "sha512-LX1qiTiC0aS8c92uZ+Wj2iNCNJyYZJIKY8/nZDKNMBfo759VYVS3RX3fKP3DznB+16sYp7++MyCz/T6fOGaRfw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.0.tgz", + "integrity": "sha512-3TGF+wVTGgQ3pAc9+5jVchES4uXUAhAt9pwv7uws4mVOxL4alvU3ue/EZ+R4XuGk94pDy7CNXjRXpPjlfZXQfw==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.6.1", + "@docusaurus/types": "3.8.0", "tslib": "^2.6.0" }, "engines": { @@ -3042,14 +3965,14 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.6.1.tgz", - "integrity": "sha512-+iMd6zRl5cJQm7nUP+7pSO/oAXsN79eHO34ME7l2YJt4GEAr70l5kkD58u2jEPpp+wSXT70c7x2A2lzJI1E8jw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.0.tgz", + "integrity": "sha512-MrnEbkigr54HkdFeg8e4FKc4EF+E9dlVwsY3XQZsNkbv3MKZnbHQ5LsNJDIKDROFe8PBf5C4qCAg5TPBpsjrjg==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.6.1", - "@docusaurus/utils": "3.6.1", - "@docusaurus/utils-common": "3.6.1", + "@docusaurus/logger": "3.8.0", + "@docusaurus/utils": "3.8.0", + "@docusaurus/utils-common": "3.8.0", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -3517,9 +4440,9 @@ "license": "MIT" }, "node_modules/@mdx-js/mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", - "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -3528,14 +4451,15 @@ "@types/mdx": "^2.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", - "estree-util-to-js": "^2.0.0", + "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", - "hast-util-to-estree": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", - "periscopic": "^3.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", @@ -3571,6 +4495,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -3583,6 +4508,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -3591,6 +4517,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -3681,20 +4608,6 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@slorber/react-ideal-image": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@slorber/react-ideal-image/-/react-ideal-image-0.0.12.tgz", - "integrity": "sha512-u8KiDTEkMA7/KAeA5ywg/P7YG4zuKhWtswfVZDH8R8HXgQsFcHIYU2WaQnGuK/Du7Wdj90I+SdFmajSGFRvoKA==", - "engines": { - "node": ">= 8.9.0", - "npm": "> 3" - }, - "peerDependencies": { - "prop-types": ">=15", - "react": ">=0.14.x", - "react-waypoint": ">=9.0.2" - } - }, "node_modules/@slorber/remark-comment": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", @@ -3983,15 +4896,6 @@ "node": ">=10.13.0" } }, - "node_modules/@types/acorn": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -4205,9 +5109,9 @@ "license": "MIT" }, "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "license": "MIT" }, "node_modules/@types/node": { @@ -4227,11 +5131,6 @@ "@types/node": "*" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, "node_modules/@types/parse5": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", @@ -4383,9 +5282,9 @@ "license": "MIT" }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, "node_modules/@webassemblyjs/ast": { @@ -4622,6 +5521,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -4676,32 +5576,33 @@ } }, "node_modules/algoliasearch": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", - "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", - "license": "MIT", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-account": "4.24.0", - "@algolia/client-analytics": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-personalization": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/recommend": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.25.0.tgz", + "integrity": "sha512-n73BVorL4HIwKlfJKb4SEzAYkR3Buwfwbh+MYxg2mloFph2fFGV58E90QTzdbfzWrLn4HE5Czx/WTjI8fcHaMg==", + "license": "MIT", + "dependencies": { + "@algolia/client-abtesting": "5.25.0", + "@algolia/client-analytics": "5.25.0", + "@algolia/client-common": "5.25.0", + "@algolia/client-insights": "5.25.0", + "@algolia/client-personalization": "5.25.0", + "@algolia/client-query-suggestions": "5.25.0", + "@algolia/client-search": "5.25.0", + "@algolia/ingestion": "1.25.0", + "@algolia/monitoring": "1.25.0", + "@algolia/recommend": "5.25.0", + "@algolia/requester-browser-xhr": "5.25.0", + "@algolia/requester-fetch": "5.25.0", + "@algolia/requester-node-http": "5.25.0" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.22.5", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.5.tgz", - "integrity": "sha512-lWvhdnc+aKOKx8jyA3bsdEgHzm/sglC4cYdMG4xSQyRiPLJVJtH/IVYZG3Hp6PkTEhQqhyVYkeP9z2IlcHJsWw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.25.0.tgz", + "integrity": "sha512-vQoK43U6HXA9/euCqLjvyNdM4G2Fiu/VFp4ae0Gau9sZeIKBPvUPnXfLYAe65Bg7PFuw03coeu5K6lTPSXRObw==", "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" @@ -4710,45 +5611,6 @@ "algoliasearch": ">= 3.1 < 6" } }, - "node_modules/algoliasearch/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "license": "MIT", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/requester-browser-xhr": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", - "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/requester-node-http": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", - "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", - "license": "MIT", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -4862,7 +5724,8 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/array-flatten": { "version": "1.1.1", @@ -4874,27 +5737,20 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/astring": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", - "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", "license": "MIT", "bin": { "astring": "bin/astring" } }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/autocomplete.js": { "version": "0.37.1", "resolved": "https://registry.npmjs.org/autocomplete.js/-/autocomplete.js-0.37.1.tgz", @@ -4904,9 +5760,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "funding": [ { "type": "opencollective", @@ -4923,11 +5779,11 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", + "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -4972,13 +5828,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", + "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", + "@babel/helper-define-polyfill-provider": "^0.6.4", "semver": "^6.3.1" }, "peerDependencies": { @@ -4995,25 +5851,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", + "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "@babel/helper-define-polyfill-provider": "^0.6.4" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5271,9 +6127,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "funding": [ { "type": "opencollective", @@ -5290,10 +6146,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -5387,16 +6243,44 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -5409,6 +6293,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -5446,9 +6331,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "version": "1.0.30001720", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", + "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", "funding": [ { "type": "opencollective", @@ -5653,6 +6538,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -5936,9 +6822,9 @@ } }, "node_modules/consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", "license": "MIT", "engines": { "node": "^14.18.0 || >=16.10.0" @@ -5949,11 +6835,6 @@ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, - "node_modules/consolidated-events": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz", - "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ==" - }, "node_modules/content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -5975,7 +6856,8 @@ "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" }, "node_modules/cookie": { "version": "0.7.1", @@ -6082,12 +6964,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", - "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", + "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", "license": "MIT", "dependencies": { - "browserslist": "^4.24.2" + "browserslist": "^4.24.4" }, "funding": { "type": "opencollective", @@ -6095,9 +6977,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", - "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.42.0.tgz", + "integrity": "sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -6175,16 +7057,116 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/css-blank-pseudo": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-7.0.1.tgz", + "integrity": "sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/css-declaration-sorter": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", "license": "ISC", "engines": { - "node": "^14 || ^16 || >=18" + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz", + "integrity": "sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-has-pseudo/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" }, "peerDependencies": { - "postcss": "^8.0.9" + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" } }, "node_modules/css-loader": { @@ -6266,6 +7248,28 @@ } } }, + "node_modules/css-prefers-color-scheme": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", + "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -6311,6 +7315,22 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/cssdb": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.3.0.tgz", + "integrity": "sha512-c7bmItIg38DgGjSwDPZOYF/2o0QU/sSgkWOMyl8votOfgFuyiFKWPesmCGEsrGLxEA9uL540cp8LdaGEjUGsZQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ], + "license": "MIT-0" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -6480,9 +7500,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", + "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -6529,6 +7549,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6595,27 +7616,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6671,35 +7671,6 @@ "detect-port": "bin/detect-port.js" } }, - "node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port-alt/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port-alt/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -6717,6 +7688,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -6931,9 +7903,9 @@ } }, "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", @@ -6975,6 +7947,20 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -6992,9 +7978,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.55", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz", - "integrity": "sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==", + "version": "1.5.161", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz", + "integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -7059,6 +8045,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -7070,18 +8057,16 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -7100,6 +8085,50 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -7227,6 +8256,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-util-to-js": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", @@ -7243,9 +8286,9 @@ } }, "node_modules/estree-util-value-to-estree": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.3.3.tgz", - "integrity": "sha512-Db+m1WSD4+mUO7UgMeKkAwdbfNWwIxLt48XF2oFU9emPfXkIu+k5/nlOj313v7wqtAPo0f9REhUvznFrPkG8CQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.0.tgz", + "integrity": "sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -7281,6 +8324,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -7491,15 +8535,16 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -7517,9 +8562,10 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -7589,6 +8635,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0" @@ -7608,6 +8655,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7623,6 +8671,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -7630,12 +8679,14 @@ "node_modules/file-loader/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" }, "node_modules/file-loader/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -7649,14 +8700,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -7761,126 +8804,6 @@ } } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "engines": { - "node": ">=6" - } - }, "node_modules/form-data-encoder": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz", @@ -8019,21 +8942,27 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -8048,6 +8977,19 @@ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "license": "ISC" }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -8114,52 +9056,17 @@ }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" } }, "node_modules/globals": { @@ -8175,6 +9082,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -8191,12 +9099,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8319,22 +9227,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -8360,9 +9256,10 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -8371,16 +9268,16 @@ } }, "node_modules/hast-util-from-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", - "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", - "hastscript": "^8.0.0", - "property-information": "^6.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" @@ -8422,9 +9319,9 @@ } }, "node_modules/hast-util-raw": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", - "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -8561,9 +9458,9 @@ } }, "node_modules/hast-util-to-estree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", - "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -8577,9 +9474,9 @@ "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.4.0", + "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" }, @@ -8589,9 +9486,9 @@ } }, "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", - "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -8604,9 +9501,9 @@ "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", - "style-to-object": "^1.0.0", + "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" }, @@ -8615,21 +9512,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", - "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", - "license": "MIT" - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", - "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.3" - } - }, "node_modules/hast-util-to-parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", @@ -8649,6 +9531,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-parse5/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/hast-util-to-string": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz", @@ -8686,15 +9578,15 @@ } }, "node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" }, "funding": { @@ -9089,21 +9981,19 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/image-size": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", - "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz", + "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==", "license": "MIT", - "dependencies": { - "queue": "6.0.2" - }, "bin": { "image-size": "bin/image-size.js" }, @@ -9116,19 +10006,11 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" }, - "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -9160,6 +10042,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", "engines": { "node": ">=8" } @@ -9193,19 +10076,11 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", "license": "MIT" }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -9250,7 +10125,8 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", @@ -9297,11 +10173,15 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9420,14 +10300,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -9448,15 +10320,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-reference": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", - "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/is-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", @@ -9466,14 +10329,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", - "engines": { - "node": ">=6" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -9576,9 +10431,10 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -9605,6 +10461,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -9613,9 +10470,9 @@ } }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -9719,9 +10576,9 @@ } }, "node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "license": "MIT", "engines": { "node": ">=14" @@ -9733,7 +10590,8 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" }, "node_modules/loader-runner": { "version": "4.3.0", @@ -9880,14 +10738,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdast-util-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", - "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", + "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", @@ -9901,9 +10769,9 @@ } }, "node_modules/mdast-util-find-and-replace": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", - "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9929,9 +10797,9 @@ } }, "node_modules/mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9953,9 +10821,9 @@ } }, "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -9999,9 +10867,9 @@ } }, "node_modules/mdast-util-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", - "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", "license": "MIT", "dependencies": { "mdast-util-from-markdown": "^2.0.0", @@ -10035,9 +10903,9 @@ } }, "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10055,9 +10923,9 @@ } }, "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10071,9 +10939,9 @@ "license": "MIT" }, "node_modules/mdast-util-gfm-footnote": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", - "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -10153,9 +11021,9 @@ } }, "node_modules/mdast-util-mdx-expression": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", - "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -10171,9 +11039,9 @@ } }, "node_modules/mdast-util-mdx-jsx": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", - "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -10186,7 +11054,6 @@ "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", - "unist-util-remove-position": "^5.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" }, @@ -10249,9 +11116,9 @@ } }, "node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -10259,6 +11126,7 @@ "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" @@ -10325,6 +11193,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -10339,9 +11208,9 @@ } }, "node_modules/micromark": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", "funding": [ { "type": "GitHub Sponsors", @@ -10374,9 +11243,9 @@ } }, "node_modules/micromark-core-commonmark": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", - "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", "funding": [ { "type": "GitHub Sponsors", @@ -10408,9 +11277,9 @@ } }, "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -10428,9 +11297,9 @@ } }, "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10448,9 +11317,9 @@ } }, "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10483,9 +11352,9 @@ } }, "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -10503,9 +11372,9 @@ } }, "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10523,9 +11392,9 @@ } }, "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10555,9 +11424,9 @@ } }, "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10575,9 +11444,9 @@ } }, "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10627,9 +11496,9 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10647,9 +11516,9 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10683,9 +11552,9 @@ } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -10703,9 +11572,9 @@ } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10723,9 +11592,9 @@ } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10757,9 +11626,9 @@ } }, "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10773,9 +11642,9 @@ "license": "MIT" }, "node_modules/micromark-extension-gfm-table": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", - "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -10790,9 +11659,9 @@ } }, "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -10810,9 +11679,9 @@ } }, "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10830,9 +11699,9 @@ } }, "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10876,9 +11745,9 @@ } }, "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -10896,9 +11765,9 @@ } }, "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10916,9 +11785,9 @@ } }, "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10932,9 +11801,9 @@ "license": "MIT" }, "node_modules/micromark-extension-mdx-expression": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", - "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10958,9 +11827,9 @@ } }, "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -10978,9 +11847,9 @@ } }, "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -10998,9 +11867,9 @@ } }, "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11014,18 +11883,18 @@ "license": "MIT" }, "node_modules/micromark-extension-mdx-jsx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.0.tgz", - "integrity": "sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", "license": "MIT", "dependencies": { - "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" @@ -11036,9 +11905,9 @@ } }, "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -11056,9 +11925,9 @@ } }, "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11076,9 +11945,9 @@ } }, "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11146,9 +12015,9 @@ } }, "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11166,9 +12035,9 @@ } }, "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11182,9 +12051,9 @@ "license": "MIT" }, "node_modules/micromark-factory-destination": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", - "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", "funding": [ { "type": "GitHub Sponsors", @@ -11203,9 +12072,9 @@ } }, "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11223,9 +12092,9 @@ } }, "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11239,9 +12108,9 @@ "license": "MIT" }, "node_modules/micromark-factory-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", - "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", "funding": [ { "type": "GitHub Sponsors", @@ -11261,9 +12130,9 @@ } }, "node_modules/micromark-factory-label/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11281,9 +12150,9 @@ } }, "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11297,9 +12166,9 @@ "license": "MIT" }, "node_modules/micromark-factory-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.1.tgz", - "integrity": "sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11314,6 +12183,7 @@ "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", @@ -11322,10 +12192,30 @@ "vfile-message": "^4.0.0" } }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11343,9 +12233,9 @@ } }, "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11395,9 +12285,9 @@ "license": "MIT" }, "node_modules/micromark-factory-title": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", - "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", "funding": [ { "type": "GitHub Sponsors", @@ -11417,9 +12307,9 @@ } }, "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -11437,9 +12327,9 @@ } }, "node_modules/micromark-factory-title/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11457,9 +12347,9 @@ } }, "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11473,9 +12363,9 @@ "license": "MIT" }, "node_modules/micromark-factory-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", - "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11495,9 +12385,9 @@ } }, "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -11515,9 +12405,9 @@ } }, "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11535,9 +12425,9 @@ } }, "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11587,9 +12477,9 @@ "license": "MIT" }, "node_modules/micromark-util-chunked": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", - "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", "funding": [ { "type": "GitHub Sponsors", @@ -11606,9 +12496,9 @@ } }, "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11622,9 +12512,9 @@ "license": "MIT" }, "node_modules/micromark-util-classify-character": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", - "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11643,9 +12533,9 @@ } }, "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11663,9 +12553,9 @@ } }, "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11679,9 +12569,9 @@ "license": "MIT" }, "node_modules/micromark-util-combine-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", - "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", "funding": [ { "type": "GitHub Sponsors", @@ -11699,9 +12589,9 @@ } }, "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", - "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", "funding": [ { "type": "GitHub Sponsors", @@ -11718,9 +12608,9 @@ } }, "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11734,9 +12624,9 @@ "license": "MIT" }, "node_modules/micromark-util-decode-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", - "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11756,9 +12646,9 @@ } }, "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11776,9 +12666,9 @@ } }, "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11792,9 +12682,9 @@ "license": "MIT" }, "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "funding": [ { "type": "GitHub Sponsors", @@ -11808,9 +12698,9 @@ "license": "MIT" }, "node_modules/micromark-util-events-to-acorn": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", - "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", "funding": [ { "type": "GitHub Sponsors", @@ -11823,7 +12713,6 @@ ], "license": "MIT", "dependencies": { - "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", @@ -11834,9 +12723,9 @@ } }, "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11850,9 +12739,9 @@ "license": "MIT" }, "node_modules/micromark-util-html-tag-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", - "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", "funding": [ { "type": "GitHub Sponsors", @@ -11866,9 +12755,9 @@ "license": "MIT" }, "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", - "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11885,9 +12774,9 @@ } }, "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11901,9 +12790,9 @@ "license": "MIT" }, "node_modules/micromark-util-resolve-all": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", - "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", "funding": [ { "type": "GitHub Sponsors", @@ -11920,9 +12809,9 @@ } }, "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11941,9 +12830,9 @@ } }, "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11961,9 +12850,9 @@ } }, "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11977,9 +12866,9 @@ "license": "MIT" }, "node_modules/micromark-util-subtokenize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", - "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "funding": [ { "type": "GitHub Sponsors", @@ -11999,9 +12888,9 @@ } }, "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -12031,9 +12920,9 @@ "license": "MIT" }, "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { "type": "GitHub Sponsors", @@ -12047,9 +12936,9 @@ "license": "MIT" }, "node_modules/micromark/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -12067,9 +12956,9 @@ } }, "node_modules/micromark/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -12087,9 +12976,9 @@ } }, "node_modules/micromark/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -12316,9 +13205,9 @@ "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" }, "node_modules/node-emoji": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", - "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", "license": "MIT", "dependencies": { "@sindresorhus/is": "^4.6.0", @@ -12340,9 +13229,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "license": "MIT" }, "node_modules/nopt": { @@ -12509,14 +13398,16 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -12609,6 +13500,15 @@ "node": ">=14.16" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -12643,6 +13543,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -12653,6 +13554,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", @@ -12666,12 +13583,16 @@ "node": ">=8" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/package-json": { @@ -12704,6 +13625,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -12712,13 +13634,12 @@ } }, "node_modules/parse-entities": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", - "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", - "character-entities": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", @@ -12741,6 +13662,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -12761,12 +13683,12 @@ "license": "ISC" }, "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "license": "MIT", "dependencies": { - "entities": "^4.5.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -12785,6 +13707,18 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -12837,7 +13771,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-to-regexp": { "version": "1.9.0", @@ -12851,21 +13786,11 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/periscopic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", - "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -12889,137 +13814,392 @@ "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "license": "MIT", "dependencies": { - "find-up": "^6.3.0" + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss": { + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz", + "integrity": "sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.10.tgz", + "integrity": "sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-10.0.0.tgz", + "integrity": "sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-10.0.0.tgz", + "integrity": "sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=14.16" + "node": "^14 || ^16 || >=18.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.4.31" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "license": "MIT", "dependencies": { - "find-up": "^3.0.0" + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=8" + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" } }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/postcss-custom-media": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.6.tgz", + "integrity": "sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "dependencies": { - "locate-path": "^3.0.0" + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/postcss-custom-properties": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.5.tgz", + "integrity": "sha512-UWf/vhMapZatv+zOuqlfLmYXeOhhHLh8U8HAKGI2VJ00xLRYoAJh4xv8iX6FB6+TLXeDnm0DBLMi00E0hodbQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/postcss-custom-selectors": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.5.tgz", + "integrity": "sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "engines": { "node": ">=4" } }, - "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "node_modules/postcss-dir-pseudo-class": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-9.0.1.tgz", + "integrity": "sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==", "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" + "type": "github", + "url": "https://github.com/sponsors/csstools" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "opencollective", + "url": "https://opencollective.com/csstools" } ], - "license": "MIT", + "license": "MIT-0", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/postcss-calc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", - "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "license": "MIT", "engines": { "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.2" + "postcss": "^8.4.31" } }, - "node_modules/postcss-colormin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", - "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", "license": "MIT", - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-api": "^3.0.0", - "colord": "^2.9.3", - "postcss-value-parser": "^4.2.0" + "engines": { + "node": "^14 || ^16 || >=18.0" }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "license": "MIT", "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -13027,14 +14207,25 @@ "postcss": "^8.4.31" } }, - "node_modules/postcss-convert-values": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", - "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-unused": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", "license": "MIT", "dependencies": { - "browserslist": "^4.23.0", - "postcss-value-parser": "^4.2.0" + "postcss-selector-parser": "^6.0.16" }, "engines": { "node": "^14 || ^16 || >=18.0" @@ -13043,67 +14234,193 @@ "postcss": "^8.4.31" } }, - "node_modules/postcss-discard-comments": { + "node_modules/postcss-double-position-gradients": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", - "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.2.tgz", + "integrity": "sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-10.0.1.tgz", + "integrity": "sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=4" + } + }, + "node_modules/postcss-focus-within": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-9.0.1.tgz", + "integrity": "sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { - "postcss": "^8.4.31" + "postcss": "^8.4" } }, - "node_modules/postcss-discard-duplicates": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", - "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", "license": "MIT", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-6.0.0.tgz", + "integrity": "sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=18" }, "peerDependencies": { - "postcss": "^8.4.31" + "postcss": "^8.4" } }, - "node_modules/postcss-discard-empty": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", - "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", - "license": "MIT", - "engines": { - "node": "^14 || ^16 || >=18.0" + "node_modules/postcss-image-set-function": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-7.0.0.tgz", + "integrity": "sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", - "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", - "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=18" }, "peerDependencies": { - "postcss": "^8.4.31" + "postcss": "^8.4" } }, - "node_modules/postcss-discard-unused": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", - "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", - "license": "MIT", + "node_modules/postcss-lab-function": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz", + "integrity": "sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.16" + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=18" }, "peerDependencies": { - "postcss": "^8.4.31" + "postcss": "^8.4" } }, "node_modules/postcss-loader": { @@ -13128,6 +14445,31 @@ "webpack": "^5.0.0" } }, + "node_modules/postcss-logical": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.1.0.tgz", + "integrity": "sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/postcss-merge-idents": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", @@ -13297,6 +14639,90 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-nesting": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", + "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz", + "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-normalize-charset": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", @@ -13430,6 +14856,28 @@ "postcss": "^8.4.31" } }, + "node_modules/postcss-opacity-percentage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-3.0.0.tgz", + "integrity": "sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/postcss-ordered-values": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", @@ -13446,6 +14894,191 @@ "postcss": "^8.4.31" } }, + "node_modules/postcss-overflow-shorthand": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-6.0.0.tgz", + "integrity": "sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-10.0.0.tgz", + "integrity": "sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.0.tgz", + "integrity": "sha512-cl13sPBbSqo1Q7Ryb19oT5NZO5IHFolRbIMdgDq4f9w1MHYiL6uZS7uSsjXJ1KzRIcX5BMjEeyxmAevVXENa3Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-cascade-layers": "^5.0.1", + "@csstools/postcss-color-function": "^4.0.10", + "@csstools/postcss-color-mix-function": "^3.0.10", + "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.0", + "@csstools/postcss-content-alt-text": "^2.0.6", + "@csstools/postcss-exponential-functions": "^2.0.9", + "@csstools/postcss-font-format-keywords": "^4.0.0", + "@csstools/postcss-gamut-mapping": "^2.0.10", + "@csstools/postcss-gradients-interpolation-method": "^5.0.10", + "@csstools/postcss-hwb-function": "^4.0.10", + "@csstools/postcss-ic-unit": "^4.0.2", + "@csstools/postcss-initial": "^2.0.1", + "@csstools/postcss-is-pseudo-class": "^5.0.1", + "@csstools/postcss-light-dark-function": "^2.0.9", + "@csstools/postcss-logical-float-and-clear": "^3.0.0", + "@csstools/postcss-logical-overflow": "^2.0.0", + "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", + "@csstools/postcss-logical-resize": "^3.0.0", + "@csstools/postcss-logical-viewport-units": "^3.0.4", + "@csstools/postcss-media-minmax": "^2.0.9", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", + "@csstools/postcss-nested-calc": "^4.0.0", + "@csstools/postcss-normalize-display-values": "^4.0.0", + "@csstools/postcss-oklab-function": "^4.0.10", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-random-function": "^2.0.1", + "@csstools/postcss-relative-color-syntax": "^3.0.10", + "@csstools/postcss-scope-pseudo-class": "^4.0.1", + "@csstools/postcss-sign-functions": "^1.1.4", + "@csstools/postcss-stepped-value-functions": "^4.0.9", + "@csstools/postcss-text-decoration-shorthand": "^4.0.2", + "@csstools/postcss-trigonometric-functions": "^4.0.9", + "@csstools/postcss-unset-value": "^4.0.0", + "autoprefixer": "^10.4.21", + "browserslist": "^4.24.5", + "css-blank-pseudo": "^7.0.1", + "css-has-pseudo": "^7.0.2", + "css-prefers-color-scheme": "^10.0.0", + "cssdb": "^8.3.0", + "postcss-attribute-case-insensitive": "^7.0.1", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^7.0.10", + "postcss-color-hex-alpha": "^10.0.0", + "postcss-color-rebeccapurple": "^10.0.0", + "postcss-custom-media": "^11.0.6", + "postcss-custom-properties": "^14.0.5", + "postcss-custom-selectors": "^8.0.5", + "postcss-dir-pseudo-class": "^9.0.1", + "postcss-double-position-gradients": "^6.0.2", + "postcss-focus-visible": "^10.0.1", + "postcss-focus-within": "^9.0.1", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^6.0.0", + "postcss-image-set-function": "^7.0.0", + "postcss-lab-function": "^7.0.10", + "postcss-logical": "^8.1.0", + "postcss-nesting": "^13.0.1", + "postcss-opacity-percentage": "^3.0.0", + "postcss-overflow-shorthand": "^6.0.0", + "postcss-page-break": "^3.0.4", + "postcss-place": "^10.0.0", + "postcss-pseudo-class-any-link": "^10.0.1", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^8.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-10.0.1.tgz", + "integrity": "sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-reduce-idents": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", @@ -13483,13 +15116,60 @@ "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-8.0.1.tgz", + "integrity": "sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "node": ">=4" } }, "node_modules/postcss-selector-parser": { @@ -13688,9 +15368,9 @@ } }, "node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", "funding": { "type": "github", @@ -13762,15 +15442,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "license": "MIT", - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -13788,7 +15459,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "5.1.1", @@ -13876,124 +15548,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", - "dependencies": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-dev-utils/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/react-dev-utils/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-dev-utils/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -14006,11 +15560,6 @@ "react": "^18.2.0" } }, - "node_modules/react-error-overlay": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", - "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" - }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", @@ -14038,15 +15587,15 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-view-lite": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", - "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.4.1.tgz", + "integrity": "sha512-fwFYknRIBxjbFm0kBDrzgBy1xa5tDg2LyXXBepC5f1b+MY3BUClMCsvanMPn089JbV1Eg3nZcrp0VCuH43aXnA==", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + "react": "^18.0.0 || ^19.0.0" } }, "node_modules/react-loadable": { @@ -14125,25 +15674,6 @@ "react": ">=15" } }, - "node_modules/react-waypoint": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/react-waypoint/-/react-waypoint-10.3.0.tgz", - "integrity": "sha512-iF1y2c1BsoXuEGz08NoahaLFIGI9gTUAAOKip96HUmylRT6DUtpgoBPjk/Y8dfcFVmfVDvUzWjNXpZyKTOV0SQ==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "consolidated-events": "^1.1.0 || ^2.0.0", - "prop-types": "^15.0.0", - "react-is": "^17.0.1 || ^18.0.0" - }, - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-waypoint/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -14168,32 +15698,68 @@ "node": ">=8.10.0" } }, - "node_modules/reading-time": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", - "license": "MIT" + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "node_modules/recma-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz", + "integrity": "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==", + "license": "MIT", "dependencies": { - "resolve": "^1.1.6" + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" }, - "engines": { - "node": ">= 0.10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", "dependencies": { - "minimatch": "^3.0.5" + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/regenerate": { @@ -14219,25 +15785,16 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, "node_modules/regexpu-core": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", - "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "license": "MIT", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", - "regjsparser": "^0.11.0", + "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -14277,9 +15834,9 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", - "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.0.2" @@ -14288,6 +15845,18 @@ "regjsparser": "bin/parser" } }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/rehype-parse": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-7.0.1.tgz", @@ -14464,6 +16033,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -14473,9 +16057,9 @@ } }, "node_modules/remark-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", - "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", + "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -14521,9 +16105,9 @@ } }, "node_modules/remark-gfm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", - "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -14539,9 +16123,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", - "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", + "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", "license": "MIT", "dependencies": { "mdast-util-mdx": "^3.0.0", @@ -14569,9 +16153,9 @@ } }, "node_modules/remark-rehype": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", - "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -14725,17 +16309,21 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -14749,6 +16337,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", "engines": { "node": ">=4" } @@ -14782,9 +16371,10 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -14804,11 +16394,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rtl-detect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", - "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" - }, "node_modules/rtlcss": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", @@ -14845,6 +16430,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -14888,6 +16474,12 @@ "loose-envify": "^1.1.0" } }, + "node_modules/schema-dts": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.5.tgz", + "integrity": "sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==", + "license": "Apache-2.0" + }, "node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -14908,9 +16500,9 @@ } }, "node_modules/search-insights": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.2.tgz", - "integrity": "sha512-zFNpOpUO+tY2D85KrxJ+aqwnIfdEGi06UH2+xEb+Bp9Mwznmauqc9djbnBibJO5mpfUPPa8st6Sx65+vbeO45g==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", "license": "MIT", "peer": true }, @@ -15261,22 +16853,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -15416,6 +16992,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -15553,9 +17130,9 @@ } }, "node_modules/std-env": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", - "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", "license": "MIT" }, "node_modules/streamx": { @@ -15705,13 +17282,22 @@ "webpack": "^5.27.0" } }, + "node_modules/style-to-js": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz", + "integrity": "sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.8" + } + }, "node_modules/style-to-object": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", - "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.1.1" + "inline-style-parser": "0.2.4" } }, "node_modules/stylehacks": { @@ -15745,6 +17331,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -15959,11 +17546,6 @@ "b4a": "^1.6.4" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -15980,6 +17562,15 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -16160,6 +17751,7 @@ "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16315,20 +17907,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -16389,9 +17967,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -16409,7 +17987,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -16508,6 +18086,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "mime-types": "^2.1.27", @@ -16534,6 +18113,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16549,6 +18129,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -16556,12 +18137,14 @@ "node_modules/url-loader/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" }, "node_modules/url-loader/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -16570,6 +18153,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -16581,6 +18165,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -16646,13 +18231,12 @@ } }, "node_modules/vfile": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz", - "integrity": "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" }, "funding": { @@ -16937,6 +18521,7 @@ "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", @@ -17298,18 +18883,10 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, "node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", "license": "MIT", "engines": { "node": ">=12.20" diff --git a/site/package.json b/site/package.json index f590603572..c44366ecd4 100644 --- a/site/package.json +++ b/site/package.json @@ -18,9 +18,9 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.6.1", - "@docusaurus/plugin-ideal-image": "^3.6.1", - "@docusaurus/preset-classic": "^3.6.1", + "@docusaurus/core": "^3.8.0", + "@docusaurus/plugin-ideal-image": "^3.8.0", + "@docusaurus/preset-classic": "^3.8.0", "@mdx-js/react": "^3.0.0", "@types/react": "^18.3.7", "clsx": "^2.0.0", @@ -32,9 +32,9 @@ "sharp": "^0.33.5" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.5.2", - "@docusaurus/tsconfig": "^3.5.2", - "@docusaurus/types": "^3.5.2", + "@docusaurus/module-type-aliases": "^3.8.0", + "@docusaurus/tsconfig": "^3.8.0", + "@docusaurus/types": "^3.8.0", "css-loader": "^7.1.2", "style-loader": "^4.0.0", "typescript": "^5.6.2" From a5084b760c2b0bbf304d44af0b4d4505cd53a74c Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 27 Jun 2025 16:08:35 -0400 Subject: [PATCH 059/448] deps(build): bump base and build images to azure linux 3.0 (#1645) # Description Moving to azurelinux 3.0 for base and build images as mariner 2.0 is being deprecated. Also bumping to go v1.24.3 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- cli/Dockerfile | 8 +++---- controller/Dockerfile | 35 ++++++++++++++-------------- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-2019 | 7 +++--- controller/Dockerfile.windows-2022 | 8 +++---- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 7 +++--- go.mod | 4 ++-- go.sum | 2 -- operator/Dockerfile | 9 ++++--- operator/Dockerfile.windows-2019 | 7 +++--- operator/Dockerfile.windows-2022 | 7 +++--- shell/Dockerfile | 2 +- test/image/Dockerfile | 6 ++--- 15 files changed, 57 insertions(+), 57 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 11e2a864c3..5823178bf4 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -22,8 +22,8 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -X "github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName"="$AGENT_IMAGE_NAME"" \ -a -o kubectl-retina cli/main.go -# mcr.microsoft.com/cbl-mariner/distroless/minimal:2.0 -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/cbl-mariner/distroless/minimal@sha256:db87903c5d4d9d6760e86a274914efd6a3bb5914c0b5a6c6b35350ec297fea4f +# skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c WORKDIR / COPY --from=builder /workspace/kubectl-retina . diff --git a/controller/Dockerfile b/controller/Dockerfile index c4c315583a..056e26d670 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -2,21 +2,20 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS golang -# skopeo inspect docker://mcr.microsoft.com/cbl-mariner/base/core:2.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/cbl-mariner/base/core@sha256:8deab931d4af66264253cce66471a04742dc6f8d5d175d4c18e930eda615c0aa AS mariner-core +# skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d AS azurelinux-core -# skopeo inspect docker://mcr.microsoft.com/cbl-mariner/distroless/minimal:2.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/cbl-mariner/distroless/minimal@sha256:0b09ee9e988e338f86432484c980c9c334d2b35b3bec6ce14298b754ecb6460b AS mariner-distroless +# skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS azurelinux-distroless -# mcr.microsoft.com/windows/servercore:ltsc2019 -FROM mcr.microsoft.com/windows/servercore@sha256:6fdf140282a2f809dae9b13fe441635867f0a27c33a438771673b8da8f3348a4 AS ltsc2019 - -# mcr.microsoft.com/windows/servercore:ltsc2022 -FROM mcr.microsoft.com/windows/servercore@sha256:45952938708fbde6ec0b5b94de68bcdec3f8c838be018536b1e9e5bd95e6b943 AS ltsc2022 +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/servercore@sha256:862b24ccf5e399fc3bea746c7ac68c16f3fbcfa199532a3e506b7e03e57217b9 AS ltsc2019 +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/servercore@sha256:c489e1737a833a111f0f35b28257b1071d30b6db6b9ee50e88b7c08b901efc67 AS ltsc2022 # build stages @@ -28,7 +27,7 @@ ARG GOOS=linux # default to linux ENV GOARCH=${GOARCH} ENV GOOS=${GOOS} RUN if [ "$GOOS" = "linux" ] ; then \ - tdnf install -y clang16 lld16 bpftool libbpf-devel; \ + tdnf install -y clang lld bpftool libbpf-devel; \ fi COPY ./pkg/plugin /go/src/github.com/microsoft/retina/pkg/plugin WORKDIR /go/src/github.com/microsoft/retina @@ -79,9 +78,9 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /go/bin/ret # tools image -FROM mariner-core AS tools +FROM azurelinux-core AS tools RUN tdnf install -y \ - clang16 \ + clang \ iproute \ iptables \ tcpdump \ @@ -109,7 +108,7 @@ RUN echo "Hubble version: $HUBBLE_VERSION" && \ rm hubble-linux-${HUBBLE_ARCH}.tar.gz && rm hubble-linux-${HUBBLE_ARCH}.tar.gz.sha256sum # init final image -FROM mariner-distroless AS init +FROM azurelinux-distroless AS init COPY --from=init-bin /go/bin/retina/initretina /retina/initretina COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib @@ -117,9 +116,9 @@ ENTRYPOINT ["./retina/initretina"] # agent final image -# mcr.microsoft.com/cbl-mariner/distroless/minimal:2.0 -# mcr.microsoft.com/cbl-mariner/distroless/minimal@sha256:63a0a70ceaa1320bc6eb98b81106667d43e46b674731ea8d28e4de1b87e0747f -FROM mariner-distroless AS agent +# mcr.microsoft.com/azurelinux/distroless/minimal:3.0 +# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c +FROM azurelinux-distroless AS agent COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib COPY --from=tools /tmp/bin/ /bin diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index ab8b0b66c4..933e871477 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 1a9961d7f2..c88d547d60 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index aa611c8737..24ca5b917a 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder # Build args ARG VERSION @@ -16,7 +16,8 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/co RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ # Copy into final image -FROM mcr.microsoft.com/windows/servercore:ltsc2019 as final +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/servercore@sha256:862b24ccf5e399fc3bea746c7ac68c16f3fbcfa199532a3e506b7e03e57217b9 as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 9613edc936..7963d88fc9 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder # Build args ARG VERSION @@ -15,8 +15,8 @@ COPY . . RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/controller.exe -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" ./controller/ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ -# Copy into final image -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore:ltsc2022 as final +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:c489e1737a833a111f0f35b28257b1071d30b6db6b9ee50e88b7c08b901efc67 as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 29ed0063ee..545faf9a86 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:b156a5187b5d22ca866fe14fd232b0de04da111394507fe96efb21e75484fbe6 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:e88cdedc8ab0299e85c1c54dede140d4f4c1c4ee595b3d9d37b4a9a103eb0a2e AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 67a1f0b67c..dcddfb32f2 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:b156a5187b5d22ca866fe14fd232b0de04da111394507fe96efb21e75484fbe6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:e88cdedc8ab0299e85c1c54dede140d4f4c1c4ee595b3d9d37b4a9a103eb0a2e AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . @@ -23,7 +23,8 @@ RUN go build -v -o captureworkload.exe -ldflags="-X github.com/microsoft/retina/ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver:ltsc2022 AS final +# skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:23fa4e796f4d02d462beadb844f8985ca4583b1b0f75295137f5968dab255b09 AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/go.mod b/go.mod index 16e78d7fc1..3a520b4d2a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/microsoft/retina -go 1.24.2 +go 1.24.3 require ( github.com/go-chi/chi/v5 v5.2.2 @@ -260,7 +260,6 @@ require ( require ( github.com/Azure/azure-container-networking/zapai v0.0.3 - github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 @@ -351,6 +350,7 @@ require ( github.com/Antonboom/errname v1.0.0 // indirect github.com/Antonboom/nilnil v1.0.1 // indirect github.com/Antonboom/testifylint v1.5.2 // indirect + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.4.0 // indirect diff --git a/go.sum b/go.sum index 94c79e4f44..d3ece3f30f 100644 --- a/go.sum +++ b/go.sum @@ -478,8 +478,6 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= diff --git a/operator/Dockerfile b/operator/Dockerfile index 11a8650cc1..079cc31b27 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -7,7 +7,6 @@ ARG APP_INSIGHTS_ID WORKDIR /workspace COPY . . -# Install jq, not sure why this went missing in the 1.24.1-2-cbl-mariner2.0 base go image. RUN tdnf install -y jq # Default linux/architecture. @@ -25,8 +24,8 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -a -o retina-operator operator/main.go ##################### controller ####################### -# mcr.microsoft.com/cbl-mariner/distroless/minimal:2.0 -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/cbl-mariner/distroless/minimal@sha256:db87903c5d4d9d6760e86a274914efd6a3bb5914c0b5a6c6b35350ec297fea4f +# skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index 3fbc78cbb1..65097f97d7 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder # Build args ARG VERSION @@ -15,7 +15,8 @@ COPY . . RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" -o -o /usr/bin/retina-operator.exe retina-operator operator/main.go # Copy into final image -FROM mcr.microsoft.com/windows/nanoserver:ltsc2019 +# skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/nanoserver@sha256:7c720f345ff7784cee12a5464bb5d5222c6348bd6da2cd29d666e49867958b0e COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index aab0dc48fa..8e596795db 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder # Build args ARG VERSION @@ -15,7 +15,8 @@ COPY . . RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" -o -o /usr/bin/retina-operator.exe retina-operator operator/main.go # Copy into final image -FROM mcr.microsoft.com/windows/nanoserver:ltsc2022 +# skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/nanoserver@sha256:23fa4e796f4d02d462beadb844f8985ca4583b1b0f75295137f5968dab255b09 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/shell/Dockerfile b/shell/Dockerfile index d530bf6635..642881a55b 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:b46476be0b5c9691ad20f78871819950c01433bdfad81d72c61618f4a6202b25 +FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d RUN tdnf install -y \ bind-utils \ diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 6eca2d3df4..20c40e6723 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,10 +1,10 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-cbl-mariner2.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8404e234fac0f624a120a43573098923a37c7e4755aebdb47783ff6212de3163 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder ENV CGO_ENABLED=0 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina -RUN tdnf install -y clang16 lld16 bpftool libbpf-devel make git jq +RUN tdnf install -y clang lld bpftool libbpf-devel make git jq RUN go generate /go/src/github.com/microsoft/retina/pkg/plugin/... # RUN go mod edit -module retina # RUN make all generate From 94c832688f7d660d67336c9d59a97ac6f5abe560 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 19:55:53 -0400 Subject: [PATCH 060/448] deps: bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 in the go_modules group (#1719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the go_modules group with 1 update: [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure). Updates `github.com/go-viper/mapstructure/v2` from 2.2.1 to 2.3.0
Release notes

Sourced from github.com/go-viper/mapstructure/v2's releases.

v2.3.0

What's Changed

New Contributors

Full Changelog: https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0

Commits
  • 8c61ec1 Merge pull request #80 from rostislaved/feature-allow-unset-pointer
  • df765f4 Merge pull request #106 from go-viper/update-linter
  • 5f34b05 update linter
  • 36de1e1 Merge pull request #105 from go-viper/error-refactor
  • 6a283a3 chore: update error type doc
  • 599cb73 Merge pull request #101 from go-viper/dependabot/github_actions/github/codeql...
  • ed3f921 feat: remove value from error messages
  • a3f8b22 revert: error message change
  • 9661f6d feat: add common error interface
  • f12f6c7 Merge pull request #102 from m1k1o/prettify-errors2
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-viper/mapstructure/v2&package-manager=go_modules&previous-version=2.2.1&new-version=2.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3a520b4d2a..4f0140dd4a 100644 --- a/go.mod +++ b/go.mod @@ -458,7 +458,7 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.3.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gofrs/flock v0.12.1 // indirect diff --git a/go.sum b/go.sum index d3ece3f30f..3b63b7e052 100644 --- a/go.sum +++ b/go.sum @@ -657,8 +657,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= +github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= From abecb12f974377e8b72d26edd434a87cfbe2cfb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 23:56:23 -0400 Subject: [PATCH 061/448] chore(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /site in the npm_and_yarn group across 1 directory (#1697) Bumps the npm_and_yarn group with 1 update in the /site directory: [brace-expansion](https://github.com/juliangruber/brace-expansion). Updates `brace-expansion` from 1.1.11 to 1.1.12
Release notes

Sourced from brace-expansion's releases.

v1.1.12

  • pkg: publish on tag 1.x c460dbd
  • fmt ccb8ac6
  • Fix potential ReDoS Vulnerability or Inefficient Regular Expression (#65) c3c73c8

https://github.com/juliangruber/brace-expansion/compare/v1.1.11...v1.1.12

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=brace-expansion&package-manager=npm_and_yarn&previous-version=1.1.11&new-version=1.1.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 4eef53f870..b3e0223df3 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -6107,9 +6107,10 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" From d615e5208530598d8ed5b39386a20b3737cd246f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Jun 2025 16:59:31 -0400 Subject: [PATCH 062/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.29.14 to 1.29.17 (#1717) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.29.14 to 1.29.17.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.29.14&new-version=1.29.17)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 24 ++++++++++++------------ go.sum | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 4f0140dd4a..f2afd4d7bf 100644 --- a/go.mod +++ b/go.mod @@ -47,19 +47,19 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect - github.com/aws/smithy-go v1.22.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect + github.com/aws/smithy-go v1.22.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -271,9 +271,9 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.36.3 - github.com/aws/aws-sdk-go-v2/config v1.29.14 - github.com/aws/aws-sdk-go-v2/credentials v1.17.67 + github.com/aws/aws-sdk-go-v2 v1.36.5 + github.com/aws/aws-sdk-go-v2/config v1.29.17 + github.com/aws/aws-sdk-go-v2/credentials v1.17.70 github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 diff --git a/go.sum b/go.sum index 3b63b7e052..a8b2df4130 100644 --- a/go.sum +++ b/go.sum @@ -240,22 +240,22 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= -github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= +github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= +github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= -github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= -github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= -github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= +github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= +github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70/go.mod h1:M+lWhhmomVGgtuPOhO85u4pEa3SmssPTdcYpP/5J/xc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6WmlVKLFFXgWYAGoJosorxzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM= @@ -264,26 +264,26 @@ github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7H github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 h1:4nm2G6A4pV9rdlWzGMPv4BNtQp22v1hg3yrtkYpeLl8= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 h1:BRXS0U76Z8wfF+bnkilA2QwpIch6URlm++yPUt9QPmQ= github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3/go.mod h1:bNXKFFyaiVvWuR6O16h/I1724+aXe/tAkA9/QS01t5k= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= -github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k= -github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f/go.mod h1:rAE739ssmE5O5fLuQ2y8uHdmOJaelE5I0Es3SxV0y1A= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From dba21bccfda7427700999208f7c511b007d4922a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Jun 2025 20:23:21 -0400 Subject: [PATCH 063/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.7.0 to 0.8.3 (#1689) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.7.0 to 0.8.3.
Commits
  • 595dc3e build(deps): bump the all group in /pkg/azclient with 17 updates (#9180)
  • 96ce7c7 build(deps): bump the all group with 23 updates (#9181)
  • a04c238 build(deps): bump the all group in /health-probe-proxy with 2 updates (#9179)
  • 27fddb2 build(deps): bump the all group with 4 updates (#9189)
  • 2f6ede1 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity (#9186)
  • 1d8ffe0 Merge pull request #9178 from nilo19/doc/example
  • a9c492a doc: Bump the image versions in readme and examples
  • e3ce95e fix: CVE-2025-22871 (#9162)
  • 817ada5 Merge pull request #9171 from nilo19/fix/flaky
  • 46fc4c3 Merge pull request #9172 from nilo19/fix/kubelet-deprecated-flag
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.7.0&new-version=0.8.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 22 +++++++++++----------- go.sum | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index f2afd4d7bf..f73a9b1f17 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.9.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.7.0 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.3 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 ) @@ -28,8 +28,8 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.29 // indirect @@ -210,11 +210,11 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.31.0 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/mod v0.25.0 // indirect + golang.org/x/text v0.26.0 // indirect + golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.33.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect @@ -241,7 +241,7 @@ require ( github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.15.0 golang.org/x/sys v0.33.0 @@ -261,7 +261,7 @@ require ( require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 @@ -354,7 +354,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.4.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.5.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.6.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0 // indirect github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect diff --git a/go.sum b/go.sum index a8b2df4130..d28f8600a6 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= @@ -79,8 +79,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontai github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0/go.mod h1:gYq8wyDgv6JLhGbAU6gg8amCPgQWRE+aCvrV2gyzdfs= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v5 v5.0.0 h1:5n7dPVqsWfVKw+ZiEKSd3Kzu7gwBkbEBkeXb8rgaE9Q= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v5 v5.0.0/go.mod h1:HcZY0PHPo/7d75p99lB6lK0qYOP4vLRJUBpiehYXtLQ= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.5.0 h1:8deM0E7Il/6jxRU9Kgv8kKm3uq3O6Gh6NVNqADa4zbU= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.5.0/go.mod h1:PhSVsfd99UdSWx7VAnbHr5i1O4WQ3YkYBFqQpSOx7oA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.6.0 h1:xkWEcbsnJWid3rOf/S/LOHy1I55JA+4kw/f8Tnm+Onc= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.6.0/go.mod h1:OWKfCmX4X3Vp2w7GSx1LZn8566tOHJBA6K0IAUVNYx0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 h1:MRPU8Bge2f9tkfG3PCr4vEnqXl8XOSjlhuK3l+8Hvkc= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0/go.mod h1:xYrOYxajQvXMlp6M1E3amlaqPDXspyJxmjqTsGo6Jmw= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= @@ -105,10 +105,10 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1. github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1 h1:mrkDCdkMsD4l9wjFGhofFHFrV43Y3c53RSLKOCJ5+Ow= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1/go.mod h1:hPv41DbqMmnxcGralanA/kVlfdH5jv3T4LxGku2E1BY= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S6wk65vfC6m3FIxJ+i5QDyN9JWwXI8Hb0Img10hU= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= @@ -575,8 +575,8 @@ github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-faker/faker/v4 v4.6.0 h1:6aOPzNptRiDwD14HuAnEtlTa+D1IfFuEHO8+vEFwjTs= -github.com/go-faker/faker/v4 v4.6.0/go.mod h1:ZmrHuVtTTm2Em9e0Du6CJ9CADaLEzGXW62z1YqFH0m0= +github.com/go-faker/faker/v4 v4.6.1 h1:xUyVpAjEtB04l6XFY0V/29oR332rOSPWV4lU8RwDt4k= +github.com/go-faker/faker/v4 v4.6.1/go.mod h1:arSdxNCSt7mOhdk8tEolvHeIJ7eX4OX80wXjKKvkKBY= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -1617,8 +1617,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1645,8 +1645,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1686,8 +1686,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= @@ -1795,10 +1795,10 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1831,8 +1831,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= 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= @@ -1963,8 +1963,8 @@ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.7.0 h1:YJP+XePFQPPgsFITSXSQUj9k1rQ3x+e3qDG/F+pil5E= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.7.0/go.mod h1:V8lGsM5QG2kqfQJjZ/7AetgG66KoHGKh0lw4bq2fjUg= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.3 h1:5L8f18QbkfvCHtWqoXSgVXOB2maEkxTkEKn8NsUa00M= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.3/go.mod h1:wAsdQiPDaJbZo2ZgZG6Je70w/xEz/60AqfaLww5TNoU= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= From ab7865765118bcac15c9bca81521f97c5ed6b025 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Jun 2025 22:28:52 -0400 Subject: [PATCH 064/448] deps: bump google.golang.org/grpc from 1.72.0 to 1.73.0 (#1661) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.0 to 1.73.0.
Release notes

Sourced from google.golang.org/grpc's releases.

Release 1.73.0

New Features

  • balancer/ringhash: move LB policy from xds/internal to exported path to facilitate use without xds (#8249)
  • xds: enable least request LB policy by default. It can be disabled by setting GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST=false in your environment. (#8253)
  • grpc: add a CallAuthority Call Option that can be used to overwrite the http :authority header on per-RPC basis. (#8068)
  • stats/opentelemetry: add trace event for name resolution delay. (#8074)
  • health: added List method to gRPC Health service. (#8155)
  • ringhash: implement features from gRFC A76. (#8159)
  • xds: add functionality to support SPIFFE Bundle Maps as roots of trust in XDS which can be enabled by setting GRPC_EXPERIMENTAL_XDS_MTLS_SPIFFE=true. (#8167, #8180, #8229, #8343)

Bug Fixes

  • xds: locality ID metric label is changed to make it consistent with gRFC A78. (#8256)
  • client: fail RPCs on the client when using extremely short contexts that expire before the grpc-timeout header is created. (#8312)
  • server: non-positive grpc-timeout header values are now rejected. This is consistent with the gRPC protocol spec. (#8290)
  • xds: fix reported error string when LRS load reporting interval is invalid. (#8224)

Performance Improvements

  • credentials/alts: improve read performance by optimizing buffer copies and allocations. (#8271)
  • server: improve performance of RPC handling by avoid a status proto copy (#8282)

Documentation

  • examples/features/opentelemetry: modify example to demonstrate tracing using OpenTelemtry plugin. (#8056)

Release 1.72.2

Bug Fixes

  • client: restore support for NO_PROXY environment variable when connecting to locally-resolved addresses (case 2 from gRFC A1). (#8329)
  • balancer/least_request: fix panic on resolver errors. (#8333)

Release 1.72.1

Bug Fixes

  • client: HTTP Proxy connections are no longer attempted for addresses with non-TCP network types. (#8215)
  • client: Fix bug that causes RPCs to fail with status INTERNAL instead of CANCELLED or DEADLINE_EXCEEDED when receiving a RST_STREAM frame in the middle of the gRPC message. (#8289)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.72.0&new-version=1.73.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index f73a9b1f17..3a588e04fa 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ retract ( ) require ( - cel.dev/expr v0.20.0 // indirect + cel.dev/expr v0.23.0 // indirect code.cloudfoundry.org/clock v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect @@ -67,7 +67,7 @@ require ( github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a // indirect github.com/cilium/lumberjack/v2 v2.4.1 // indirect github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect - github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect + github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/containerd v1.7.27 // indirect github.com/containerd/continuity v0.4.4 // indirect @@ -217,7 +217,7 @@ require ( golang.org/x/tools v0.33.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/apiserver v0.32.3 // indirect @@ -305,7 +305,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - google.golang.org/grpc v1.72.0 + google.golang.org/grpc v1.73.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 @@ -364,7 +364,7 @@ require ( github.com/Crocmagnon/fatcontext v0.7.1 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect @@ -629,7 +629,7 @@ require ( go-simpler.org/musttag v0.13.0 // indirect go-simpler.org/sloglint v0.9.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect diff --git a/go.sum b/go.sum index d28f8600a6..6188932990 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ 4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= -cel.dev/expr v0.20.0 h1:OunBvVCfvpWlt4dN7zg3FM6TDkzOePe1+foGJ9AXeeI= -cel.dev/expr v0.20.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cel.dev/expr v0.23.0 h1:wUb94w6OYQS4uXraxo9U+wUAs9jT47Xvl4iPgAwM2ss= +cel.dev/expr v0.23.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= @@ -159,8 +159,8 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rW github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 h1:f2Qw/Ehhimh5uO1fayV0QIW7DShEQqhtUfhYc+cBPlw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0/go.mod h1:2bIszWvQRlJVmJLiuLhukLImRjKPcYdzzsx6darK02A= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= @@ -407,8 +407,8 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= -github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f h1:C5bqEmzEPLsHm9Mv73lSE9e9bKV23aB1vxOsmZrkl3k= +github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -1522,8 +1522,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0 h1:x7sPooQCwSg27SjtQee8GyIIRTQcF4s7eSkac6F2+VA= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0/go.mod h1:4K5UXgiHxV484efGs42ejD7E2J/sIlepYgdGoPXe7hE= -go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao= -go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= +go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA= +go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 h1:GuQXpvSXNjpswpweIem84U9BNauqHHi2w1GtNAalvpM= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0/go.mod h1:CkmxekdHco4d7thFJNPQ7Mby4jMBgZUclnrxT4e+ryk= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= @@ -1851,8 +1851,8 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY= -google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg= +google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= +google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1863,8 +1863,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= -google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= +google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 91e4901bd80e282bd2367946b9b9332fa7193639 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Mon, 30 Jun 2025 10:00:17 +0100 Subject: [PATCH 065/448] chore(shell): add option to Unconfined AppArmor and SecComp profiles (#1715) # Description Creation option to create retina shell pod with Unconfined [AppArmor](https://kubernetes.io/docs/tutorials/security/apparmor/) and [SecComp](https://kubernetes.io/docs/tutorials/security/seccomp/) Profiles. Both AppArmor and SecComp are security features that restrict privilege and resource access. By enabling options to create a pod with unconfined profiles, tools that require more privileges can be used in troubleshooting scenarios. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Manual test: ![image](https://github.com/user-attachments/assets/17808891-6578-414d-b721-109dc0abc759) ![image](https://github.com/user-attachments/assets/740e132a-1e8b-4bfe-b3bb-315649fff674) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- cli/cmd/shell.go | 6 ++++++ shell/manifests.go | 12 ++++++++++++ shell/shell.go | 3 +++ 3 files changed, 21 insertions(+) diff --git a/cli/cmd/shell.go b/cli/cmd/shell.go index b388c720eb..d8f5c101c4 100644 --- a/cli/cmd/shell.go +++ b/cli/cmd/shell.go @@ -24,6 +24,8 @@ var ( retinaShellImageVersion string mountHostFilesystem bool allowHostFilesystemWrite bool + appArmorUnconfined bool + seccompUnconfined bool hostPID bool capabilities []string timeout time.Duration @@ -113,6 +115,8 @@ var shellCmd = &cobra.Command{ AllowHostFilesystemWrite: allowHostFilesystemWrite, HostPID: hostPID, Capabilities: capabilities, + AppArmorUnconfined: appArmorUnconfined, + SeccompUnconfined: seccompUnconfined, Timeout: timeout, } @@ -163,6 +167,8 @@ func init() { shellCmd.Flags().BoolVar(&hostPID, "host-pid", false, "Set HostPID on the shell container. Applies only to nodes, not pods.") shellCmd.Flags().StringSliceVarP(&capabilities, "capabilities", "c", []string{}, "Add capabilities to the shell container") shellCmd.Flags().DurationVar(&timeout, "timeout", defaultTimeout, "The maximum time to wait for the shell container to start") + shellCmd.Flags().BoolVar(&appArmorUnconfined, "apparmor-unconfined", false, "Set AppArmor profile type to unconfined. Applies only to nodes, not pods.") + shellCmd.Flags().BoolVar(&seccompUnconfined, "seccomp-unconfined", false, "Set Seccomp profile type to unconfined. Applies only to nodes, not pods.") // configFlags and matchVersion flags are used to load kubeconfig. // This uses the same mechanism as `kubectl debug` to connect to apiserver and attach to containers. diff --git a/shell/manifests.go b/shell/manifests.go index 72a5df0989..4dd2188ff4 100644 --- a/shell/manifests.go +++ b/shell/manifests.go @@ -69,6 +69,18 @@ func hostNetworkPodForNodeDebug(config Config, debugPodNamespace, nodeName strin }) } + if config.AppArmorUnconfined { + pod.Spec.Containers[0].SecurityContext.AppArmorProfile = &v1.AppArmorProfile{ + Type: v1.AppArmorProfileTypeUnconfined, + } + } + + if config.SeccompUnconfined { + pod.Spec.Containers[0].SecurityContext.SeccompProfile = &v1.SeccompProfile{ + Type: v1.SeccompProfileTypeUnconfined, + } + } + return pod } diff --git a/shell/shell.go b/shell/shell.go index c85a07338c..fd0cdee1ec 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -22,6 +22,9 @@ type Config struct { // Host filesystem access applies only to nodes, not pods. MountHostFilesystem bool AllowHostFilesystemWrite bool + + AppArmorUnconfined bool + SeccompUnconfined bool } // RunInPod starts an interactive shell in a pod by creating and attaching to an ephemeral container. From a8f25f00322f866b0152d4a69c35b7ecb463f63e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 13:15:09 -0400 Subject: [PATCH 066/448] deps: bump sigs.k8s.io/yaml from 1.4.0 to 1.5.0 (#1725) Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.4.0 to 1.5.0.
Release notes

Sourced from sigs.k8s.io/yaml's releases.

v1.5.0

Full Changelog: https://github.com/kubernetes-sigs/yaml/compare/v1.4.0...v1.5.0

Commits
  • 0f318dc Merge pull request #134 from kubernetes-sigs/forgot-to-add-redirects-for-cons...
  • b8fc0c0 Forgot to add redirects for v3 constants
  • 8eaa802 Merge pull request #133 from kubernetes-sigs/deprecate-code-in-goyaml.v3-goya...
  • 69e45c1 Deprecate code in goyaml.v2/goyaml.v3 directories and redirect
  • 0fe7da3 Merge pull request #125 from kragniz/go-1.24
  • 14cbb88 Test against go 1.24.x
  • c6ac2c9 Merge pull request #126 from kragniz/remove-travis
  • 203ded9 Remove old travisci config file
  • b9a9b1c Merge pull request #106 from ThatsMrTalbot/patch-1
  • 4c6913f fix: wrap errors returned by JSON unmarshal
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/yaml&package-manager=go_modules&previous-version=1.4.0&new-version=1.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 ++++-- go.sum | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3a588e04fa..b9ac30a6de 100644 --- a/go.mod +++ b/go.mod @@ -255,11 +255,12 @@ require ( k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect - sigs.k8s.io/yaml v1.4.0 + sigs.k8s.io/yaml v1.5.0 ) require ( github.com/Azure/azure-container-networking/zapai v0.0.3 + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 @@ -350,7 +351,6 @@ require ( github.com/Antonboom/errname v1.0.0 // indirect github.com/Antonboom/nilnil v1.0.1 // indirect github.com/Antonboom/testifylint v1.5.2 // indirect - github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.4.0 // indirect @@ -638,6 +638,8 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v3 v3.0.3 // indirect gocloud.dev v0.37.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect diff --git a/go.sum b/go.sum index 6188932990..22341a02b1 100644 --- a/go.sum +++ b/go.sum @@ -478,6 +478,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= @@ -1596,6 +1598,10 @@ go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= gocloud.dev v0.37.0 h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro= @@ -1992,7 +1998,8 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= From 47f567fef2cb076a724dbdf7bd95f937139ad9d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:22:18 -0400 Subject: [PATCH 067/448] deps: bump github.com/jellydator/ttlcache/v3 from 3.3.0 to 3.4.0 (#1724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/jellydator/ttlcache/v3](https://github.com/jellydator/ttlcache) from 3.3.0 to 3.4.0.
Release notes

Sourced from github.com/jellydator/ttlcache/v3's releases.

v3.4.0

What's Changed

New Contributors

Full Changelog: https://github.com/jellydator/ttlcache/compare/v3.3.0...v3.4.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/jellydator/ttlcache/v3&package-manager=go_modules&previous-version=3.3.0&new-version=3.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b9ac30a6de..f97eed3867 100644 --- a/go.mod +++ b/go.mod @@ -287,7 +287,7 @@ require ( github.com/google/gopacket v1.1.19 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/inspektor-gadget/inspektor-gadget v0.27.0 - github.com/jellydator/ttlcache/v3 v3.3.0 + github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 github.com/mdlayher/netlink v1.7.2 github.com/microsoft/ApplicationInsights-Go v0.4.4 diff --git a/go.sum b/go.sum index 22341a02b1..104496469b 100644 --- a/go.sum +++ b/go.sum @@ -908,8 +908,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc= -github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw= +github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY= +github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From e7bfb679613212a8ff8e772cd3501fdcc5ee9805 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 19:36:48 -0400 Subject: [PATCH 068/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.8.3 to 0.8.4 (#1722) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.8.3 to 0.8.4.
Commits
  • c208ec2 build(deps): bump the all group in /pkg/azclient with 2 updates (#9209)
  • c811ba8 build(deps): bump the all group in /tests with 5 updates (#9206)
  • 6dd2b39 build(deps): bump the all group across 1 directory with 13 updates (#9205)
  • 448e16a Updates linter version and args in Makefile (#9196)
  • 2cb15c6 build(deps): bump k8s.io/component-base (#9198)
  • 436d945 build(deps): bump the all group (#9204)
  • f4cad34 build(deps): bump k8s.io/client-go (#9201)
  • ae8888c build(deps): bump sigs.k8s.io/cloud-provider-azure/pkg/azclient (#9202)
  • 4cd0c76 build(deps): bump softprops/action-gh-release in the all group (#9200)
  • 9fecb88 build(deps): bump k8s.io/apimachinery in /kubetest2-aks in the all group (#9197)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.8.3&new-version=0.8.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f97eed3867..a61e819357 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.9.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.3 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 ) diff --git a/go.sum b/go.sum index 104496469b..f43198bd12 100644 --- a/go.sum +++ b/go.sum @@ -1969,8 +1969,8 @@ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.3 h1:5L8f18QbkfvCHtWqoXSgVXOB2maEkxTkEKn8NsUa00M= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.3/go.mod h1:wAsdQiPDaJbZo2ZgZG6Je70w/xEz/60AqfaLww5TNoU= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.4 h1:OJUTH2EYD4tXL3rc9JgZMh0joQX9MEHooZv68mA+k14= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.4/go.mod h1:RzF4KeJQXjHpHJ2gq2t5KqRrTDf5y5+vrHUTLCBunzo= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= From 988613a53adf661ee53d50c8afb20fbab2d23a3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 22:49:29 -0400 Subject: [PATCH 069/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.79.3 to 1.82.0 (#1723) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.79.3 to 1.82.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.79.3&new-version=1.82.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index a61e819357..182c992df4 100644 --- a/go.mod +++ b/go.mod @@ -46,16 +46,16 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect @@ -275,7 +275,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.36.5 github.com/aws/aws-sdk-go-v2/config v1.29.17 github.com/aws/aws-sdk-go-v2/credentials v1.17.70 - github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 + github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index f43198bd12..7360e9b2c7 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,8 @@ github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0= @@ -258,24 +258,24 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 h1:GMYy2EOWfzdP3wfVAGXBNKY5vK4K8vMET4sYOYltmqs= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36/go.mod h1:gDhdAV6wL3PmPqBhiPbnlS447GoWs8HTTOYef9/9Inw= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 h1:4nm2G6A4pV9rdlWzGMPv4BNtQp22v1hg3yrtkYpeLl8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 h1:nAP2GYbfh8dd2zGZqFRSMlq+/F6cMPBUuCsGAMkN074= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4/go.mod h1:LT10DsiGjLWh4GbjInf9LQejkYEhBgBCjLG5+lvk4EE= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 h1:qcLWgdhq45sDM9na4cvXax9dyLitn8EYBRl8Ak4XtG4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17/go.mod h1:M+jkjBFZ2J6DJrjMv2+vkBbuht6kxJYtJiwoVgX4p4U= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 h1:BRXS0U76Z8wfF+bnkilA2QwpIch6URlm++yPUt9QPmQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3/go.mod h1:bNXKFFyaiVvWuR6O16h/I1724+aXe/tAkA9/QS01t5k= +github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 h1:JubM8CGDDFaAOmBrd8CRYNr49ZNgEAiLwGwgNMdS0nw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= From 8a9b961e302f2cec207372edc2781fb17a0d2ad7 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 2 Jul 2025 13:00:11 +0100 Subject: [PATCH 070/448] chore(cli): refactor CLI to allow better testing interface + add tests (#1693) # Description kubectl-retina CLI does not have e2e tests to validate its behavior. For that, some refactoring is needed. This PR: * refactors CLI code to allow injection of fake kubeclient for testing purposes. This allows the creation of tests that can validate that kubernetes resources are created as expected. * Add some tests for `capture create` and `capture delete` commands to confirm that main arguments are behaving as expected. Other tests will be added in the future and this code will be a reference for that. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos --- cli/cmd/capture/capture.go | 59 ++++-- cli/cmd/capture/create.go | 350 ++++++++++++++++----------------- cli/cmd/capture/create_test.go | 335 +++++++++++++++++++++++++++++++ cli/cmd/capture/delete.go | 112 +++++------ cli/cmd/capture/delete_test.go | 192 ++++++++++++++++++ cli/cmd/capture/download.go | 89 ++++----- cli/cmd/capture/list.go | 56 +++--- cli/cmd/capture/table_util.go | 9 +- cli/main.go | 8 +- 9 files changed, 879 insertions(+), 331 deletions(-) create mode 100644 cli/cmd/capture/create_test.go create mode 100644 cli/cmd/capture/delete_test.go diff --git a/cli/cmd/capture/capture.go b/cli/cmd/capture/capture.go index c7c6861b12..082edb4d5e 100644 --- a/cli/cmd/capture/capture.go +++ b/cli/cmd/capture/capture.go @@ -4,28 +4,63 @@ package capture import ( - "github.com/microsoft/retina/cli/cmd" + "time" + "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/kubernetes" ) -var opts = struct { +type Opts struct { genericclioptions.ConfigFlags - Name *string -}{ + Name *string + blobUpload string + debug bool + duration time.Duration + excludeFilter string + hostPath string + includeFilter string + includeMetadata bool + interfaces string + jobNumLimit int + maxSize int + namespaceSelectors string + nodeNames string + nodeSelectors string + nowait bool + packetSize int + podSelectors string + pvc string + s3AccessKeyID string + s3Bucket string + s3Endpoint string + s3Path string + s3Region string + s3SecretAccessKey string + tcpdumpFilter string +} + +var opts = Opts{ Name: new(string), } -const defaultName = "retina-capture" +const DefaultName = "retina-capture" -var capture = &cobra.Command{ - Use: "capture", - Short: "Capture network traffic", -} +func NewCommand(kubeClient kubernetes.Interface) *cobra.Command { + capture := &cobra.Command{ + Use: "capture", + Short: "Capture network traffic", + Long: "Capture network traffic from pods in a Kubernetes cluster.", + } -func init() { - cmd.Retina.AddCommand(capture) opts.ConfigFlags = *genericclioptions.NewConfigFlags(true) opts.AddFlags(capture.PersistentFlags()) - capture.PersistentFlags().StringVar(opts.Name, "name", defaultName, "The name of the Retina Capture") + capture.PersistentFlags().StringVar(opts.Name, "name", DefaultName, "The name of the Retina Capture") + + capture.AddCommand(NewCreateSubCommand(kubeClient)) + capture.AddCommand(NewDeleteSubCommand(kubeClient)) + capture.AddCommand(NewDownloadSubCommand()) + capture.AddCommand(NewListSubCommand()) + + return capture } diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index 33f84fcd45..e7863aa5ed 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -33,34 +33,6 @@ import ( "github.com/microsoft/retina/pkg/config" ) -var ( - blobUpload string - debug bool - duration time.Duration - excludeFilter string - hostPath string - includeFilter string - includeMetadata bool - interfaces string - jobNumLimit int - maxSize int - namespace string - namespaceSelectors string - nodeNames string - nodeSelectors string - nowait bool - packetSize int - podSelectors string - pvc string - s3AccessKeyID string - s3Bucket string - s3Endpoint string - s3Path string - s3Region string - s3SecretAccessKey string - tcpdumpFilter string -) - const ( DefaultDebug bool = false DefaultDuration time.Duration = 1 * time.Minute @@ -110,99 +82,143 @@ var createExample = templates.Examples(i18n.T(` --s3-secret-access-key "your-secret-access-key" `)) -var createCapture = &cobra.Command{ - Use: "create", - Short: "Create a Retina Capture", - Example: createExample, - RunE: func(*cobra.Command, []string) error { - kubeConfig, err := opts.ToRESTConfig() - if err != nil { - return errors.Wrap(err, "failed to compose k8s rest config") - } +func create(kubeClient kubernetes.Interface) error { + // Set namespace. If --namespace is not set, use namespace on user's context + ns, _, err := opts.ConfigFlags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return errors.Wrap(err, "failed to get namespace from kubeconfig") + } - kubeClient, err := kubernetes.NewForConfig(kubeConfig) - if err != nil { - return errors.Wrap(err, "failed to initialize kubernetes client") - } + if opts.Namespace == nil || *opts.Namespace == "" { + opts.Namespace = &ns + } - // Set namespace. If --namespace is not set, use namespace on user's context - ns, _, err := opts.ConfigFlags.ToRawKubeConfigLoader().Namespace() - if err != nil { - return errors.Wrap(err, "failed to get namespace from kubeconfig") - } + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) + defer cancel() + + capture, err := createCaptureF(ctx, kubeClient) + if err != nil { + return err + } - if opts.Namespace == nil || *opts.Namespace == "" { - opts.Namespace = &ns + jobsCreated, err := createJobs(ctx, kubeClient, capture) + if err != nil { + retinacmd.Logger.Error("Failed to create job", zap.Error(err)) + return err + } + if opts.nowait { + retinacmd.Logger.Info("Please manually delete all capture jobs") + if capture.Spec.OutputConfiguration.BlobUpload != nil { + retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload)) } + if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { + retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName)) + } + printCaptureResult(jobsCreated) + return nil + } - ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) - defer cancel() + // Wait until all jobs finish then delete the jobs before the timeout, otherwise print jobs created to + // let the customer recycle them. + retinacmd.Logger.Info("Waiting for capture jobs to finish") - capture, err := createCaptureF(ctx, kubeClient) - if err != nil { - return err - } + allJobsCompleted := waitUntilJobsComplete(ctx, kubeClient, jobsCreated) - jobsCreated, err := createJobs(ctx, kubeClient, capture) - if err != nil { - retinacmd.Logger.Error("Failed to create job", zap.Error(err)) - return err + // Delete all jobs created only if they all completed, otherwise keep the jobs for debugging. + if allJobsCompleted { + retinacmd.Logger.Info("Deleting jobs as all jobs are completed") + jobsFailedToDelete := deleteJobs(ctx, kubeClient, jobsCreated) + if len(jobsFailedToDelete) != 0 { + retinacmd.Logger.Info("Please manually delete capture jobs failed to delete", zap.String("namespace", *opts.Namespace), zap.String("job list", strings.Join(jobsFailedToDelete, ","))) } - if nowait { - retinacmd.Logger.Info("Please manually delete all capture jobs") - if capture.Spec.OutputConfiguration.BlobUpload != nil { - retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload)) + + if capture.Spec.OutputConfiguration.BlobUpload != nil { + err = deleteSecret(ctx, kubeClient, capture.Spec.OutputConfiguration.BlobUpload) + if err != nil { + retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it", + zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload), zap.Error(err)) } - if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { - retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName)) + } + + if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { + err = deleteSecret(ctx, kubeClient, &capture.Spec.OutputConfiguration.S3Upload.SecretName) + if err != nil { + retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it", + zap.String("namespace", *opts.Namespace), + zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName), + zap.Error(err), + ) } - printCaptureResult(jobsCreated) - return nil } - // Wait until all jobs finish then delete the jobs before the timeout, otherwise print jobs created to - // let the customer recycle them. - retinacmd.Logger.Info("Waiting for capture jobs to finish") + if len(jobsFailedToDelete) == 0 && err == nil { + retinacmd.Logger.Info("Done for deleting jobs") + } + return nil + } + + retinacmd.Logger.Info("Not all job are completed in the given time") + retinacmd.Logger.Info("Please manually delete the Capture") - allJobsCompleted := waitUntilJobsComplete(ctx, kubeClient, jobsCreated) + return getCaptureAndPrintCaptureResult(ctx, kubeClient, capture.Name, *opts.Namespace) +} - // Delete all jobs created only if they all completed, otherwise keep the jobs for debugging. - if allJobsCompleted { - retinacmd.Logger.Info("Deleting jobs as all jobs are completed") - jobsFailedToDelete := deleteJobs(ctx, kubeClient, jobsCreated) - if len(jobsFailedToDelete) != 0 { - retinacmd.Logger.Info("Please manually delete capture jobs failed to delete", zap.String("namespace", *opts.Namespace), zap.String("job list", strings.Join(jobsFailedToDelete, ","))) - } +func GetClientset() (*kubernetes.Clientset, error) { + kubeConfig, err := opts.ToRESTConfig() + if err != nil { + return nil, errors.Wrap(err, "failed to compose k8s rest config") + } - if capture.Spec.OutputConfiguration.BlobUpload != nil { - err = deleteSecret(ctx, kubeClient, capture.Spec.OutputConfiguration.BlobUpload) - if err != nil { - retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it", - zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload), zap.Error(err)) - } - } + kubeClient, err := kubernetes.NewForConfig(kubeConfig) + if err != nil { + return nil, errors.Wrap(err, "failed to initialize kubernetes client") + } - if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { - err = deleteSecret(ctx, kubeClient, &capture.Spec.OutputConfiguration.S3Upload.SecretName) - if err != nil { - retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it", - zap.String("namespace", *opts.Namespace), - zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName), - zap.Error(err), - ) - } - } + return kubeClient, nil +} - if len(jobsFailedToDelete) == 0 && err == nil { - retinacmd.Logger.Info("Done for deleting jobs") - } - return nil - } +func NewCreateSubCommand(kubeClient kubernetes.Interface) *cobra.Command { + createCapture := &cobra.Command{ + Use: "create", + Short: "Create a Retina Capture", + Example: createExample, + } - retinacmd.Logger.Info("Not all job are completed in the given time") - retinacmd.Logger.Info("Please manually delete the Capture") - return getCaptureAndPrintCaptureResult(ctx, kubeClient, capture.Name, *opts.Namespace) - }, + createCapture.RunE = func(*cobra.Command, []string) error { + return create(kubeClient) + } + + createCapture.Flags().DurationVar(&opts.duration, "duration", DefaultDuration, "Duration of capturing packets") + createCapture.Flags().IntVar(&opts.maxSize, "max-size", DefaultMaxSize, "Limit the capture file to MB in size which works only for Linux") //nolint:gomnd // default + createCapture.Flags().IntVar(&opts.packetSize, "packet-size", DefaultPacketSize, "Limits the each packet to bytes in size which works only for Linux") + createCapture.Flags().StringVar(&opts.nodeNames, "node-names", "", "A comma-separated list of node names to select nodes on which the network capture will be performed") + createCapture.Flags().StringVar(&opts.nodeSelectors, "node-selectors", DefaultNodeSelectors, "A comma-separated list of node labels to select nodes on which the network capture will be performed") + createCapture.Flags().StringVar(&opts.podSelectors, "pod-selectors", "", + "A comma-separated list of pod labels to select pods on which the network capture will be performed") + createCapture.Flags().StringVar(&opts.namespaceSelectors, "namespace-selectors", "", + "A comma-separated list of namespace labels to filter which namespaces will be targeted for packet capture (used with --pod-selectors)") + createCapture.Flags().StringVar(&opts.hostPath, "host-path", DefaultHostPath, "HostPath of the node to store the capture files") + createCapture.Flags().StringVar(&opts.pvc, "pvc", "", "PersistentVolumeClaim under the specified or default namespace to store capture files") + createCapture.Flags().StringVar(&opts.blobUpload, "blob-upload", "", "Blob SAS URL with write permission to upload capture files") + createCapture.Flags().StringVar(&opts.s3Region, "s3-region", "", "Region where the S3 compatible bucket is located") + createCapture.Flags().StringVar(&opts.s3Endpoint, "s3-endpoint", "", + "Endpoint for an S3 compatible storage service. Use this if you are using a custom or private S3 service that requires a specific endpoint") + createCapture.Flags().StringVar(&opts.s3Bucket, "s3-bucket", "", "Bucket in which to store capture files") + createCapture.Flags().StringVar(&opts.s3Path, "s3-path", DefaultS3Path, "Prefix path within the S3 bucket where captures will be stored") + createCapture.Flags().StringVar(&opts.s3AccessKeyID, "s3-access-key-id", "", "S3 access key id to upload capture files") + createCapture.Flags().StringVar(&opts.s3SecretAccessKey, "s3-secret-access-key", "", "S3 access secret key to upload capture files") + createCapture.Flags().StringVar(&opts.tcpdumpFilter, "tcpdump-filter", "", "Raw tcpdump flags which works only for Linux") + createCapture.Flags().StringVar(&opts.interfaces, "interfaces", "", "Comma-separated list of network interfaces to capture on (e.g., eth0,eth1)") + createCapture.Flags().StringVar(&opts.excludeFilter, "exclude-filter", "", "A comma-separated list of IP:Port pairs that are "+ + "excluded from capturing network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") + createCapture.Flags().StringVar(&opts.includeFilter, "include-filter", "", "A comma-separated list of IP:Port pairs that are "+ + "used to filter capture network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") + createCapture.Flags().BoolVar(&opts.includeMetadata, "include-metadata", DefaultIncludeMetadata, "If true, collect static network metadata into capture file") + createCapture.Flags().IntVar(&opts.jobNumLimit, "job-num-limit", DefaultJobNumLimit, "The maximum number of jobs can be created for each capture. 0 means no limit") + createCapture.Flags().BoolVar(&opts.nowait, "no-wait", DefaultNowait, "Do not wait for the long-running capture job to finish") + createCapture.Flags().BoolVar(&opts.debug, "debug", DefaultDebug, "When debug is true, a customized retina-agent image, determined by the environment variable RETINA_AGENT_IMAGE, is set") + + return createCapture } func createSecretFromBlobUpload(ctx context.Context, kubeClient kubernetes.Interface, blobUpload, captureName string) (string, error) { @@ -264,9 +280,9 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ - TcpdumpFilter: &tcpdumpFilter, + TcpdumpFilter: &opts.tcpdumpFilter, CaptureTarget: retinav1alpha1.CaptureTarget{}, - IncludeMetadata: includeMetadata, + IncludeMetadata: opts.includeMetadata, CaptureOption: retinav1alpha1.CaptureOption{}, }, }, @@ -277,40 +293,40 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti retinacmd.Logger.Info(fmt.Sprintf("Capture timestamp: %s", timestamp)) - if duration != 0 { - retinacmd.Logger.Info(fmt.Sprintf("The capture duration is set to %s", duration)) - capture.Spec.CaptureConfiguration.CaptureOption.Duration = &metav1.Duration{Duration: duration} + if opts.duration != 0 { + retinacmd.Logger.Info(fmt.Sprintf("The capture duration is set to %s", opts.duration)) + capture.Spec.CaptureConfiguration.CaptureOption.Duration = &metav1.Duration{Duration: opts.duration} } - if namespaceSelectors != "" || podSelectors != "" { + if opts.namespaceSelectors != "" || opts.podSelectors != "" { // if node selector is using the default value (aka hasn't been set by user), set it to nil to prevent clash with namespace and pod selector - if nodeSelectors == DefaultNodeSelectors { + if opts.nodeSelectors == DefaultNodeSelectors { retinacmd.Logger.Info("Overriding default node selectors value and setting it to nil. Using namespace and pod selectors. To use node selector, please remove namespace and pod selectors.") - nodeSelectors = "" + opts.nodeSelectors = "" } } - nodeSelectorLabelsMap, err := labels.ConvertSelectorToLabelsMap(nodeSelectors) + nodeSelectorLabelsMap, err := labels.ConvertSelectorToLabelsMap(opts.nodeSelectors) if err != nil { return nil, err } - podSelectorLabelsMap, err := labels.ConvertSelectorToLabelsMap(podSelectors) + podSelectorLabelsMap, err := labels.ConvertSelectorToLabelsMap(opts.podSelectors) if err != nil { return nil, err } - namespaceSelectorLabelsMap, err := labels.ConvertSelectorToLabelsMap(namespaceSelectors) + namespaceSelectorLabelsMap, err := labels.ConvertSelectorToLabelsMap(opts.namespaceSelectors) if err != nil { return nil, err } - if len(nodeSelectorLabelsMap) != 0 || len(nodeNames) != 0 { + if len(nodeSelectorLabelsMap) != 0 || opts.nodeNames != "" { capture.Spec.CaptureConfiguration.CaptureTarget.NodeSelector = &metav1.LabelSelector{} } if len(nodeSelectorLabelsMap) != 0 { capture.Spec.CaptureConfiguration.CaptureTarget.NodeSelector.MatchLabels = nodeSelectorLabelsMap } - if len(nodeNames) != 0 { - nodeNameSlice := strings.Split(nodeNames, ",") + if opts.nodeNames != "" { + nodeNameSlice := strings.Split(opts.nodeNames, ",") if len(nodeNameSlice) != 0 { capture.Spec.CaptureConfiguration.CaptureTarget.NodeSelector.MatchExpressions = []metav1.LabelSelectorRequirement{{ Key: corev1.LabelHostname, @@ -320,29 +336,32 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti } } + // Add namespace selectors if provided, regardless of other selectors if len(namespaceSelectorLabelsMap) != 0 { capture.Spec.CaptureConfiguration.CaptureTarget.NamespaceSelector = &metav1.LabelSelector{ MatchLabels: namespaceSelectorLabelsMap, } } + + // Add pod selectors if provided if len(podSelectorLabelsMap) != 0 { capture.Spec.CaptureConfiguration.CaptureTarget.PodSelector = &metav1.LabelSelector{ MatchLabels: podSelectorLabelsMap, } } - if maxSize != 0 { - retinacmd.Logger.Info(fmt.Sprintf("The capture file max size is set to %dMB", maxSize)) - capture.Spec.CaptureConfiguration.CaptureOption.MaxCaptureSize = &maxSize + if opts.maxSize != 0 { + retinacmd.Logger.Info(fmt.Sprintf("The capture file max size is set to %dMB", opts.maxSize)) + capture.Spec.CaptureConfiguration.CaptureOption.MaxCaptureSize = &opts.maxSize } - if packetSize != 0 { - retinacmd.Logger.Info(fmt.Sprintf("The capture packet size is set to %d bytes", packetSize)) - capture.Spec.CaptureConfiguration.CaptureOption.PacketSize = &packetSize + if opts.packetSize != 0 { + retinacmd.Logger.Info(fmt.Sprintf("The capture packet size is set to %d bytes", opts.packetSize)) + capture.Spec.CaptureConfiguration.CaptureOption.PacketSize = &opts.packetSize } - if interfaces != "" { - interfaceSlice := strings.Split(interfaces, ",") + if opts.interfaces != "" { + interfaceSlice := strings.Split(opts.interfaces, ",") for i := range interfaceSlice { interfaceSlice[i] = strings.TrimSpace(interfaceSlice[i]) } @@ -350,49 +369,49 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti capture.Spec.CaptureConfiguration.CaptureOption.Interfaces = interfaceSlice } - if len(hostPath) != 0 { - capture.Spec.OutputConfiguration.HostPath = &hostPath + if opts.hostPath != "" { + capture.Spec.OutputConfiguration.HostPath = &opts.hostPath } - if len(pvc) != 0 { - capture.Spec.OutputConfiguration.PersistentVolumeClaim = &pvc + if opts.pvc != "" { + capture.Spec.OutputConfiguration.PersistentVolumeClaim = &opts.pvc } - if len(blobUpload) != 0 { + if opts.blobUpload != "" { // Mount blob url as secret onto the capture pod for security concern if blob url is not empty. - secretName, err := createSecretFromBlobUpload(ctx, kubeClient, blobUpload, *opts.Name) + secretName, err := createSecretFromBlobUpload(ctx, kubeClient, opts.blobUpload, *opts.Name) if err != nil { return nil, err } capture.Spec.OutputConfiguration.BlobUpload = &secretName } - if s3Bucket != "" { - secretName, err := createSecretFromS3Upload(ctx, kubeClient, s3AccessKeyID, s3SecretAccessKey, *opts.Name) + if opts.s3Bucket != "" { + secretName, err := createSecretFromS3Upload(ctx, kubeClient, opts.s3AccessKeyID, opts.s3SecretAccessKey, *opts.Name) if err != nil { return nil, fmt.Errorf("failed to create s3 upload secret: %w", err) } capture.Spec.OutputConfiguration.S3Upload = &retinav1alpha1.S3Upload{ - Endpoint: s3Endpoint, - Bucket: s3Bucket, + Endpoint: opts.s3Endpoint, + Bucket: opts.s3Bucket, SecretName: secretName, - Region: s3Region, - Path: s3Path, + Region: opts.s3Region, + Path: opts.s3Path, } } - if len(excludeFilter) != 0 { + if opts.excludeFilter != "" { if capture.Spec.CaptureConfiguration.Filters == nil { capture.Spec.CaptureConfiguration.Filters = &retinav1alpha1.CaptureConfigurationFilters{} } - excludeFilterSlice := strings.Split(excludeFilter, ",") + excludeFilterSlice := strings.Split(opts.excludeFilter, ",") capture.Spec.CaptureConfiguration.Filters.Exclude = excludeFilterSlice } - if len(includeFilter) != 0 { + if opts.includeFilter != "" { if capture.Spec.CaptureConfiguration.Filters == nil { capture.Spec.CaptureConfiguration.Filters = &retinav1alpha1.CaptureConfigurationFilters{} } - includeFilterSlice := strings.Split(includeFilter, ",") + includeFilterSlice := strings.Split(opts.includeFilter, ",") capture.Spec.CaptureConfiguration.Filters.Include = includeFilterSlice } return capture, nil @@ -401,9 +420,9 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti func getCLICaptureConfig() config.CaptureConfig { return config.CaptureConfig{ CaptureImageVersion: buildinfo.Version, - CaptureDebug: debug, + CaptureDebug: opts.debug, CaptureImageVersionSource: captureUtils.VersionSourceCLIVersion, - CaptureJobNumLimit: jobNumLimit, + CaptureJobNumLimit: opts.jobNumLimit, } } @@ -430,15 +449,15 @@ func waitUntilJobsComplete(ctx context.Context, kubeClient kubernetes.Interface, allJobsCompleted := false // TODO: let's make the timeout and period to wait for all job to finish configurable. - var deadline time.Duration = DefaultWaitTimeout - if duration != 0 { - deadline = duration * 2 + deadline := DefaultWaitTimeout + if opts.duration != 0 { + deadline = opts.duration * 2 } - var period time.Duration = DefaultWaitPeriod + period := DefaultWaitPeriod // To print less noisy messages, we rely on duration to decide the wait period. - if period < duration/10 { - period = duration / 10 + if period < opts.duration/10 { + period = opts.duration / 10 } retinacmd.Logger.Info(fmt.Sprintf("Waiting timeout is set to %s", deadline)) @@ -495,36 +514,3 @@ func deleteJobs(ctx context.Context, kubeClient kubernetes.Interface, jobs []bat } return jobsFailedtoDelete } - -func init() { - capture.AddCommand(createCapture) - createCapture.Flags().DurationVar(&duration, "duration", DefaultDuration, "Duration of capturing packets") - createCapture.Flags().IntVar(&maxSize, "max-size", DefaultMaxSize, "Limit the capture file to MB in size which works only for Linux") //nolint:gomnd // default - createCapture.Flags().IntVar(&packetSize, "packet-size", DefaultPacketSize, "Limits the each packet to bytes in size which works only for Linux") - createCapture.Flags().StringVar(&nodeNames, "node-names", "", "A comma-separated list of node names to select nodes on which the network capture will be performed") - createCapture.Flags().StringVar(&nodeSelectors, "node-selectors", DefaultNodeSelectors, "A comma-separated list of node labels to select nodes on which the network capture will be performed") - createCapture.Flags().StringVar(&podSelectors, "pod-selectors", "", - "A comma-separated list of pod labels to select pods on which the network capture will be performed") - createCapture.Flags().StringVar(&namespaceSelectors, "namespace-selectors", "", - "A comma-separated list of namespace labels in which to apply the pod-selectors. By default, the pod namespace is specified by the flag namespace") - createCapture.Flags().StringVar(&hostPath, "host-path", DefaultHostPath, "HostPath of the node to store the capture files") - createCapture.Flags().StringVar(&pvc, "pvc", "", "PersistentVolumeClaim under the specified or default namespace to store capture files") - createCapture.Flags().StringVar(&blobUpload, "blob-upload", "", "Blob SAS URL with write permission to upload capture files") - createCapture.Flags().StringVar(&s3Region, "s3-region", "", "Region where the S3 compatible bucket is located") - createCapture.Flags().StringVar(&s3Endpoint, "s3-endpoint", "", - "Endpoint for an S3 compatible storage service. Use this if you are using a custom or private S3 service that requires a specific endpoint") - createCapture.Flags().StringVar(&s3Bucket, "s3-bucket", "", "Bucket in which to store capture files") - createCapture.Flags().StringVar(&s3Path, "s3-path", DefaultS3Path, "Prefix path within the S3 bucket where captures will be stored") - createCapture.Flags().StringVar(&s3AccessKeyID, "s3-access-key-id", "", "S3 access key id to upload capture files") - createCapture.Flags().StringVar(&s3SecretAccessKey, "s3-secret-access-key", "", "S3 access secret key to upload capture files") - createCapture.Flags().StringVar(&tcpdumpFilter, "tcpdump-filter", "", "Raw tcpdump flags which works only for Linux") - createCapture.Flags().StringVar(&interfaces, "interfaces", "", "Comma-separated list of network interfaces to capture on (e.g., eth0,eth1)") - createCapture.Flags().StringVar(&excludeFilter, "exclude-filter", "", "A comma-separated list of IP:Port pairs that are "+ - "excluded from capturing network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") - createCapture.Flags().StringVar(&includeFilter, "include-filter", "", "A comma-separated list of IP:Port pairs that are "+ - "used to filter capture network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") - createCapture.Flags().BoolVar(&includeMetadata, "include-metadata", DefaultIncludeMetadata, "If true, collect static network metadata into capture file") - createCapture.Flags().IntVar(&jobNumLimit, "job-num-limit", DefaultJobNumLimit, "The maximum number of jobs can be created for each capture. 0 means no limit") - createCapture.Flags().BoolVar(&nowait, "no-wait", DefaultNowait, "Do not wait for the long-running capture job to finish") - createCapture.Flags().BoolVar(&debug, "debug", DefaultDebug, "When debug is true, a customized retina-agent image, determined by the environment variable RETINA_AGENT_IMAGE, is set") -} diff --git a/cli/cmd/capture/create_test.go b/cli/cmd/capture/create_test.go new file mode 100644 index 0000000000..1eed7c85eb --- /dev/null +++ b/cli/cmd/capture/create_test.go @@ -0,0 +1,335 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "bytes" + "context" + "fmt" + "math/rand" + "testing" + + "github.com/microsoft/retina/pkg/label" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + clienttesting "k8s.io/client-go/testing" +) + +type testcase struct { + name string + inputName string + wantName string + inputNamespace string + wantNamespace string + inputPodSelector string + inputNsSelector string + inputNodeSelector string + wantNodes []string + wantErr bool +} + +func randomString(length int) string { + const charset = "abcdefghijklmnopqrstuvwxyz0123456789" + result := make([]byte, length) + for i := range result { + result[i] = charset[rand.Intn(len(charset))] //nolint:gosec // this random number generator is fine + } + return string(result) +} + +func argsFromTestCase(tc testcase) []string { + args := []string{"create", "--pod-selectors", tc.inputPodSelector} + if tc.inputNsSelector != "" { + args = append(args, "--namespace-selectors="+tc.inputNsSelector) + } + if tc.inputNamespace != "" { + args = append(args, "--namespace", tc.inputNamespace) + } + if tc.inputName != "" { + args = append(args, "--name", tc.inputName) + } + if tc.inputNodeSelector != "" { + args = append(args, "--node-selectors="+tc.inputNodeSelector) + } + return args +} + +func NewNode(name string) *corev1.Node { + return &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "kubernetes.io/hostname": name, + }, + }, + } +} + +func NewNamespace(name string) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "name": name, + }, + }, + } +} + +func NewClientServerPods(service, namespace string) []*corev1.Pod { + return []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "client" + service, + Namespace: namespace, + Labels: map[string]string{ + "service": service, + }, + }, + Spec: corev1.PodSpec{ + NodeName: service + "1", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "server" + service, + Namespace: namespace, + Labels: map[string]string{ + "service": service, + }, + }, + Spec: corev1.PodSpec{ + NodeName: service + "2", + }, + }, + } +} + +func TestCreateJobsWithNamespace(t *testing.T) { + // Create a fake Kubernetes client with workload and capture namespaces + newKubeclient := func() *fake.Clientset { + objects := []runtime.Object{ + NewNode("A1"), + NewNode("A2"), + NewNode("B1"), + NewNode("B2"), + NewNamespace("workload"), + NewNamespace("capture"), + } + for _, pod := range NewClientServerPods("A", "workload") { + objects = append(objects, pod) + } + for _, pod := range NewClientServerPods("B", "workload") { + objects = append(objects, pod) + } + + kubeClient := fake.NewClientset(objects...) + + // Handle job creation to set job name if not provided, which is done automatically in a real k8s cluster + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction, ok := action.(clienttesting.CreateAction) + if !ok { + return false, nil, fmt.Errorf("expected CreateAction, got %T", action) //nolint:err113 // test code + } + job := createAction.GetObject().(*batchv1.Job) + + // Set job name if unset + if job.Name == "" { + job.Name = job.GenerateName + randomString(5) + } + return false, job, nil + }) + + return kubeClient + } + + // Setup test cases + testCases := []testcase{ + { + name: "create --name=test --podSelector=service=A --namespace-selectors=name=workload", + inputName: "test", + wantName: "test", + inputNamespace: "", + wantNamespace: "default", + inputPodSelector: "service=A", + inputNsSelector: "name=workload", + wantNodes: []string{"A1", "A2"}, + wantErr: false, + }, + { + name: "create --namespace=workload --podSelector=service=A --namespace-selectors=name=workload", + inputName: "", + wantName: DefaultName, + inputNamespace: "workload", + wantNamespace: "workload", + inputPodSelector: "service=A", + inputNsSelector: "name=workload", + wantNodes: []string{"A1", "A2"}, + wantErr: false, + }, + { + name: "create --namespace=workload --podSelector=service=A", + inputName: "", + wantName: DefaultName, + inputNamespace: "workload", + wantNamespace: "workload", + inputPodSelector: "service=A", + inputNsSelector: "", + wantNodes: []string{}, + wantErr: true, + }, + { + name: "create --namespace=workload --namespace-selectors=name=workload", + inputName: "", + wantName: DefaultName, + inputNamespace: "workload", + wantNamespace: "workload", + inputPodSelector: "", + inputNsSelector: "name=workload", + wantNodes: []string{}, + wantErr: true, + }, + { + name: "create --namespace=workload --podSelector=service=B --namespace-selectors=name=workload", + inputName: "", + wantName: DefaultName, + inputNamespace: "workload", + wantNamespace: "workload", + inputPodSelector: "service=B", + inputNsSelector: "name=workload", + wantNodes: []string{"B1", "B2"}, + wantErr: false, + }, + { + name: "create --namespace=workload --node-selectors=kubernetes.io/hostname=B1", + inputName: "", + wantName: DefaultName, + inputNamespace: "workload", + wantNamespace: "workload", + inputNodeSelector: "kubernetes.io/hostname=B1", + wantNodes: []string{"B1"}, + wantErr: false, + }, + { + name: "create --namespace=workload --podSelector=service=B --namespace-selectors=name=workload --node-selectors=kubernetes.io/hostname=B1", + inputName: "", + wantName: DefaultName, + inputNamespace: "workload", + wantNamespace: "workload", + inputPodSelector: "service=B", + inputNsSelector: "name=workload", + inputNodeSelector: "kubernetes.io/hostname=B1", + wantNodes: []string{"B1"}, + wantErr: true, + }, + } + for _, tc := range testCases { + fmt.Println("\n### Running test case:", tc.name) + // Given + kubeClient := newKubeclient() + cmd := NewCommand(kubeClient) + cmd.SetArgs(argsFromTestCase(tc)) + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + t.Run(tc.name, func(t *testing.T) { + // When + err := cmd.Execute() + + // Then + + // Check the command execution + AssertError(t, err, tc) + + // Validate that jobs are created correctly + JobsCreatedCorrectly(t, kubeClient, tc) + }) + } +} + +// AssertError checks if the error matches the expected outcome based on the testcase +func AssertError(t *testing.T, err error, tc testcase) { + t.Helper() + if tc.wantErr { + if err == nil { + t.Fatalf("Expected error for test case %s, but got none", tc.name) + } + t.Skip("Successfully got expected error") + } + if err != nil { + t.Fatalf("Failed to execute command: %v", err) + } +} + +// JobsCreatedCorrectly validates that Kubernetes jobs were created correctly based on the namespace and pod selector flags +// provided to the command. It verifies that jobs are created in the right namespace and with the correct node affinity. +func JobsCreatedCorrectly(t *testing.T, kubeClient *fake.Clientset, tc testcase) { + t.Helper() + // Get created jobs + jobs, err := kubeClient.BatchV1().Jobs(tc.wantNamespace).List(context.TODO(), metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", label.CaptureNameLabel, tc.wantName), + }) + // Execution should not return an error + if err != nil { + t.Fatalf("Failed to list jobs in namespace %s: %v", tc.wantNamespace, err) + } + + // Jobs should not be nil or empty + if jobs == nil || len(jobs.Items) == 0 { + t.Fatalf("No jobs found for capture %s in namespace %s", tc.wantName, tc.wantNamespace) + } + + // Number of jobs should match expected number of nodes + if len(jobs.Items) != len(tc.wantNodes) { + t.Fatalf("Expected %d jobs, but found %d", len(tc.wantNodes), len(jobs.Items)) + } + + // Create a map of expected nodes for easier comparison + expectedNodes := make(map[string]bool) + for _, node := range tc.wantNodes { + expectedNodes[node] = true + } + matchCount := 0 + + // Validate node affinity for each job + for idx := range jobs.Items { + job := jobs.Items[idx] + + // Validate node affinity based on pod selector and namespace selector + if len(tc.wantNodes) > 0 { + if job.Spec.Template.Spec.Affinity == nil || job.Spec.Template.Spec.Affinity.NodeAffinity == nil { + t.Fatalf("Expected job to have node affinity, but none found") + } + + nodeAffinity := job.Spec.Template.Spec.Affinity.NodeAffinity + if nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { + t.Fatalf("Expected job to have required node affinity, but none found") + } + + // Look for hostname match expression + for _, nodeSelectorTerm := range nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + for _, expression := range nodeSelectorTerm.MatchExpressions { + if expression.Key == "kubernetes.io/hostname" { + // Check if all values are in expected nodes and count matches + for _, value := range expression.Values { + if expectedNodes[value] { + matchCount++ + } else { + t.Errorf("Unexpected node %s in job %s, expected nodes: %v", value, job.Name, tc.wantNodes) + } + } + } + } + } + } + } + + // Check if all expected nodes are present + if matchCount != len(tc.wantNodes) { + t.Errorf("Job's node affinity doesn't match expected nodes. Expected: %v", tc.wantNodes) + } +} diff --git a/cli/cmd/capture/delete.go b/cli/cmd/capture/delete.go index 523e359888..8c2b3fd0ab 100644 --- a/cli/cmd/capture/delete.go +++ b/cli/cmd/capture/delete.go @@ -27,76 +27,66 @@ var deleteExample = templates.Examples(i18n.T(` kubectl retina capture delete --name retina-capture-8v6wd --namespace capture `)) -var deleteCapture = &cobra.Command{ - Use: "delete", - Short: "Delete a Retina capture", - Example: deleteExample, - RunE: func(*cobra.Command, []string) error { - kubeConfig, err := opts.ToRESTConfig() - if err != nil { - return errors.Wrap(err, "") - } +func NewDeleteSubCommand(kubeClient kubernetes.Interface) *cobra.Command { + deleteCapture := &cobra.Command{ + Use: "delete", + Short: "Delete a Retina capture", + Example: deleteExample, + RunE: func(*cobra.Command, []string) error { + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) + defer cancel() - kubeClient, err := kubernetes.NewForConfig(kubeConfig) - if err != nil { - return errors.Wrap(err, "") - } - - // Set namespace. If --namespace is not set, use namespace on user's context - ns, _, err := opts.ConfigFlags.ToRawKubeConfigLoader().Namespace() - if err != nil { - return errors.Wrap(err, "failed to get namespace from kubeconfig") - } - - if opts.Namespace == nil || *opts.Namespace == "" { - opts.Namespace = &ns - } + // Set namespace. If --namespace is not set, use namespace on user's context + ns, _, err := opts.ConfigFlags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return errors.Wrap(err, "failed to get namespace from kubeconfig") + } - ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) - defer cancel() + if opts.Namespace == nil || *opts.Namespace == "" { + opts.Namespace = &ns + } - captureJobSelector := &metav1.LabelSelector{ - MatchLabels: map[string]string{ - label.CaptureNameLabel: *opts.Name, - label.AppLabel: captureConstants.CaptureAppname, - }, - } - labelSelector, _ := labels.Parse(metav1.FormatLabelSelector(captureJobSelector)) - jobListOpt := metav1.ListOptions{ - LabelSelector: labelSelector.String(), - } + captureJobSelector := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + label.CaptureNameLabel: *opts.Name, + label.AppLabel: captureConstants.CaptureAppname, + }, + } + labelSelector, _ := labels.Parse(metav1.FormatLabelSelector(captureJobSelector)) + jobListOpt := metav1.ListOptions{ + LabelSelector: labelSelector.String(), + } - jobList, err := kubeClient.BatchV1().Jobs(*opts.Namespace).List(ctx, jobListOpt) - if err != nil { - return errors.Wrap(err, "failed to list capture jobs") - } - if len(jobList.Items) == 0 { - return errors.Errorf("capture %s in namespace %s was not found", *opts.Name, *opts.Namespace) - } + jobList, err := kubeClient.BatchV1().Jobs(*opts.Namespace).List(ctx, jobListOpt) + if err != nil { + return errors.Wrap(err, "failed to list capture jobs") + } + if len(jobList.Items) == 0 { + return errors.Errorf("capture %s in namespace %s was not found", *opts.Name, *opts.Namespace) + } - for _, job := range jobList.Items { - deletePropagationBackground := metav1.DeletePropagationBackground - if err := kubeClient.BatchV1().Jobs(job.Namespace).Delete(ctx, job.Name, metav1.DeleteOptions{ - PropagationPolicy: &deletePropagationBackground, - }); err != nil { - retinacmd.Logger.Info("Failed to delete job", zap.String("job name", job.Name), zap.Error(err)) + for idx := range jobList.Items { + deletePropagationBackground := metav1.DeletePropagationBackground + if err := kubeClient.BatchV1().Jobs(jobList.Items[idx].Namespace).Delete(ctx, jobList.Items[idx].Name, metav1.DeleteOptions{ + PropagationPolicy: &deletePropagationBackground, + }); err != nil { + retinacmd.Logger.Info("Failed to delete job", zap.String("job name", jobList.Items[idx].Name), zap.Error(err)) + } } - } - for _, volume := range jobList.Items[0].Spec.Template.Spec.Volumes { - if volume.Secret != nil { - if err := kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(ctx, volume.Secret.SecretName, metav1.DeleteOptions{}); err != nil { - return errors.Wrap(err, "failed to delete capture secret") + for idx := range jobList.Items[0].Spec.Template.Spec.Volumes { + if jobList.Items[0].Spec.Template.Spec.Volumes[idx].Secret != nil { + if err := kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(ctx, jobList.Items[0].Spec.Template.Spec.Volumes[idx].Secret.SecretName, metav1.DeleteOptions{}); err != nil { + return errors.Wrap(err, "failed to delete capture secret") + } + break } - break } - } - retinacmd.Logger.Info(fmt.Sprintf("Retina Capture %q delete", *opts.Name)) + retinacmd.Logger.Info(fmt.Sprintf("Retina Capture %q delete", *opts.Name)) - return nil - }, -} + return nil + }, + } -func init() { - capture.AddCommand(deleteCapture) + return deleteCapture } diff --git a/cli/cmd/capture/delete_test.go b/cli/cmd/capture/delete_test.go new file mode 100644 index 0000000000..2a8bdc4f9a --- /dev/null +++ b/cli/cmd/capture/delete_test.go @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "bytes" + "context" + "fmt" + "testing" + + "github.com/microsoft/retina/pkg/label" + batchv1 "k8s.io/api/batch/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + clienttesting "k8s.io/client-go/testing" +) + +const ( + // Constants for creating test capture jobs + defaultCaptureJobName = "retina-capture-test" + defaultCaptureJobNamespace = "workload" +) + +type deleteTestCase struct { + name string + inputName string // name flag for delete + inputNamespace string // namespace flag for delete + jobNamespace string // namespace where the job is expected to be found + jobPodSelectors string // pod selectors for the job +} + +// newKubeclient creates a consistent fake Kubernetes client for all tests +func newKubeclient() *fake.Clientset { + objects := []runtime.Object{ + NewNode("A1"), + NewNode("A2"), + NewNode("B1"), + NewNode("B2"), + NewNamespace("default"), + NewNamespace("workload"), + } + + // Add pods to the client + for _, pod := range NewClientServerPods("A", "default") { + objects = append(objects, pod) + } + for _, pod := range NewClientServerPods("B", "workload") { + objects = append(objects, pod) + } + + kubeClient := fake.NewClientset(objects...) + + // Handle job creation to set job name if not provided, which is done automatically in a real k8s cluster + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction, ok := action.(clienttesting.CreateAction) + if !ok { + return false, nil, fmt.Errorf("expected CreateAction, got %T", action) //nolint:err113 // test code + } + job := createAction.GetObject().(*batchv1.Job) + + // Set job name if unset + if job.Name == "" { + job.Name = job.GenerateName + randomString(5) + } + return false, job, nil + }) + + return kubeClient +} + +func deleteArgs(tc deleteTestCase) []string { + args := []string{"delete"} + if tc.inputNamespace != "" { + args = append(args, "--namespace", tc.inputNamespace) + } + if tc.inputName != "" { + args = append(args, "--name", tc.inputName) + } + return args +} + +func createArgs(name, namespace, podSelectors string) []string { + // Create a default set of arguments for the create command + return []string{ + "create", + "--name=" + name, + "--namespace=" + namespace, + "--pod-selectors=" + podSelectors, + "--namespace-selectors=name=" + namespace, + } +} + +func createCapture(t *testing.T, kubeClient kubernetes.Interface, name, namespace, podSelectors string) { + createCmd := NewCommand(kubeClient) + + createCmd.SetArgs(createArgs(name, namespace, podSelectors)) + + buf := new(bytes.Buffer) + createCmd.SetOut(buf) + + err := createCmd.Execute() + if err != nil { + t.Fatalf("Failed to create capture jobs: %v", err) + } +} + +// setupDeleteTest prepares the test environment and creates jobs if needed +func setupDeleteTest(t *testing.T, tc deleteTestCase) *fake.Clientset { + // Create a Kubernetes client with test resources + kubeClient := newKubeclient() + + createCapture(t, kubeClient, tc.inputName, tc.jobNamespace, tc.jobPodSelectors) + createCapture(t, kubeClient, "do-not-delete", tc.jobNamespace, tc.jobPodSelectors) + + return kubeClient +} + +func jobExists(t *testing.T, kubeClient kubernetes.Interface, name, namespace string) bool { + jobs, err := kubeClient.BatchV1().Jobs(namespace).List( + context.TODO(), + metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", label.CaptureNameLabel, name), + }, + ) + if err != nil { + t.Fatalf("Failed to list jobs in namespace %s: %v", namespace, err) + } + + return len(jobs.Items) > 0 +} + +// jobDeletedCorrectly validates that Kubernetes jobs were deleted correctly +func jobDeletedCorrectly(t *testing.T, kubeClient *fake.Clientset, tc deleteTestCase) { + t.Helper() + + // Check if the job was deleted as expected + if jobExists(t, kubeClient, tc.inputName, tc.inputNamespace) { + t.Errorf("Expected job %s to be deleted from namespace %s, but it still exists", + tc.inputName, tc.inputNamespace) + } + + // Check if the other job in namespace is still present + if !jobExists(t, kubeClient, "do-not-delete", tc.inputNamespace) { + t.Errorf("Expected job do-not-delete in namespace %s, but it was deleted", + tc.inputNamespace) + } +} + +func TestDeleteCaptureJobs(t *testing.T) { + testCases := []deleteTestCase{ + { + name: "delete providing name only", + inputName: defaultCaptureJobName, + inputNamespace: "", + jobNamespace: "default", + jobPodSelectors: "service=A", + }, + { + name: "delete providing name and namespace", + inputName: defaultCaptureJobName, + inputNamespace: defaultCaptureJobNamespace, + jobNamespace: defaultCaptureJobNamespace, + jobPodSelectors: "service=B", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + kubeClient := setupDeleteTest(t, tc) + + // Create a delete command + deleteCmd := NewCommand(kubeClient) + + // Set command args + deleteCmd.SetArgs(deleteArgs(tc)) + buf := new(bytes.Buffer) + deleteCmd.SetOut(buf) + + // Execute the delete command + err := deleteCmd.Execute() + if err != nil { + t.Fatalf("Failed to delete capture job: %v", err) + } + + // Validate job is deleted correctly + jobDeletedCorrectly(t, kubeClient, tc) + }) + } +} diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index f6957fa27d..ac3a0776e5 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -68,48 +68,6 @@ var downloadExample = templates.Examples(i18n.T(` kubectl retina capture download --blob-url "" `)) -var downloadCapture = &cobra.Command{ - Use: "download", - Short: "Download Retina Captures", - Example: downloadExample, - RunE: func(*cobra.Command, []string) error { - viper.AutomaticEnv() - - kubeConfig, err := opts.ToRESTConfig() - if err != nil { - return errors.Wrap(err, "failed to compose k8s rest config") - } - - ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) - defer cancel() - - captureNamespace := *opts.Namespace - if captureNamespace == "" { - captureNamespace = "default" - } - - if captureName == "" && blobURL == "" { - return errors.New("either --name or --blob-url must be specified") - } - - if captureName != "" { - err = downloadFromCluster(ctx, kubeConfig, captureNamespace) - if err != nil { - return err - } - } - - if blobURL != "" { - err = downloadFromBlob() - if err != nil { - return err - } - } - - return nil - }, -} - func downloadFromCluster(ctx context.Context, config *rest.Config, namespace string) error { kubeClient, err := kubernetes.NewForConfig(config) if err != nil { @@ -404,9 +362,52 @@ func downloadFromBlob() error { return nil } -func init() { - capture.AddCommand(downloadCapture) +func NewDownloadSubCommand() *cobra.Command { + downloadCapture := &cobra.Command{ + Use: "download", + Short: "Download Retina Captures", + Example: downloadExample, + RunE: func(*cobra.Command, []string) error { + viper.AutomaticEnv() + + kubeConfig, err := opts.ToRESTConfig() + if err != nil { + return errors.Wrap(err, "failed to compose k8s rest config") + } + + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) + defer cancel() + + captureNamespace := *opts.Namespace + if captureNamespace == "" { + captureNamespace = "default" + } + + if captureName == "" && blobURL == "" { + return errors.New("either --name or --blob-url must be specified") + } + + if captureName != "" { + err = downloadFromCluster(ctx, kubeConfig, captureNamespace) + if err != nil { + return err + } + } + + if blobURL != "" { + err = downloadFromBlob() + if err != nil { + return err + } + } + + return nil + }, + } + downloadCapture.Flags().StringVar(&blobURL, "blob-url", "", "Blob URL from which to download") downloadCapture.Flags().StringVar(&captureName, "name", "", "The name of a the capture") downloadCapture.Flags().StringVarP(&outputPath, "output", "o", DefaultOutputPath, "Path to save the downloaded capture") + + return downloadCapture } diff --git a/cli/cmd/capture/list.go b/cli/cmd/capture/list.go index 43e5667f05..8beda63b06 100644 --- a/cli/cmd/capture/list.go +++ b/cli/cmd/capture/list.go @@ -25,35 +25,35 @@ var listExample = templates.Examples(i18n.T(` kubectl retina capture list --all-namespaces `)) -var listCaptures = &cobra.Command{ - Use: "list", - Short: "List Retina Captures", - Example: listExample, - RunE: func(*cobra.Command, []string) error { - kubeConfig, err := opts.ToRESTConfig() - if err != nil { - return errors.Wrap(err, "failed to compose k8s rest config") - } - - kubeClient, err := kubernetes.NewForConfig(kubeConfig) - if err != nil { - return errors.Wrap(err, "failed to initialize kubernetes client") - } - - // Create a context that is canceled when a termination signal is received - ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) - defer cancel() - - captureNamespace := *opts.Namespace - if allNamespaces { - captureNamespace = "" - } - return listCapturesInNamespaceAndPrintCaptureResults(ctx, kubeClient, captureNamespace) - }, -} +func NewListSubCommand() *cobra.Command { + listCaptures := &cobra.Command{ + Use: "list", + Short: "List Retina Captures", + Example: listExample, + RunE: func(*cobra.Command, []string) error { + kubeConfig, err := opts.ToRESTConfig() + if err != nil { + return errors.Wrap(err, "failed to compose k8s rest config") + } + + kubeClient, err := kubernetes.NewForConfig(kubeConfig) + if err != nil { + return errors.Wrap(err, "failed to initialize kubernetes client") + } + + // Create a context that is canceled when a termination signal is received + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) + defer cancel() + + captureNamespace := *opts.Namespace + if allNamespaces { + captureNamespace = "" + } + return listCapturesInNamespaceAndPrintCaptureResults(ctx, kubeClient, captureNamespace) + }, + } -func init() { - capture.AddCommand(listCaptures) listCaptures.Flags().BoolVarP(&allNamespaces, "all-namespaces", "A", allNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + return listCaptures } diff --git a/cli/cmd/capture/table_util.go b/cli/cmd/capture/table_util.go index 4d81fb8e93..65fc343bc4 100644 --- a/cli/cmd/capture/table_util.go +++ b/cli/cmd/capture/table_util.go @@ -21,7 +21,7 @@ import ( "k8s.io/client-go/kubernetes" ) -func getCaptureAndPrintCaptureResult(ctx context.Context, kubeClient *kubernetes.Clientset, name, namespace string) error { +func getCaptureAndPrintCaptureResult(ctx context.Context, kubeClient kubernetes.Interface, name, namespace string) error { return listCapturesAndPrintCaptureResults(ctx, kubeClient, name, namespace) } @@ -30,7 +30,7 @@ func listCapturesInNamespaceAndPrintCaptureResults(ctx context.Context, kubeClie } // listCapturesAndPrintCaptureResults list captures and print the running jobs into properly aligned text. -func listCapturesAndPrintCaptureResults(ctx context.Context, kubeClient *kubernetes.Clientset, name, namespace string) error { +func listCapturesAndPrintCaptureResults(ctx context.Context, kubeClient kubernetes.Interface, name, namespace string) error { jobListOpt := metav1.ListOptions{} if len(name) != 0 { captureJobSelector := &metav1.LabelSelector{ @@ -87,7 +87,10 @@ func printCaptureResult(captureJobs []batchv1.Job) { for i := range jobs { job := &jobs[i] - completions := fmt.Sprintf("%d/%d", job.Status.Succeeded, *job.Spec.Completions) + var completions string + if job.Spec.Completions != nil { + completions = fmt.Sprintf("%d/%d", job.Status.Succeeded, *job.Spec.Completions) + } age := durationUtil.HumanDuration(time.Since(job.CreationTimestamp.Time)) fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", captureNamespace, captureName, job.Name, completions, age) } diff --git a/cli/main.go b/cli/main.go index b6aa648ea0..c32c138aae 100644 --- a/cli/main.go +++ b/cli/main.go @@ -7,10 +7,16 @@ import ( "os" "github.com/microsoft/retina/cli/cmd" - _ "github.com/microsoft/retina/cli/cmd/capture" + "github.com/microsoft/retina/cli/cmd/capture" ) func main() { + kubeClient, err := capture.GetClientset() + if err != nil { + fmt.Printf("Failed to get Kubernetes client: %v\n", err) + os.Exit(1) + } + cmd.Retina.AddCommand(capture.NewCommand(kubeClient)) if err := cmd.Retina.Execute(); err != nil { fmt.Println(err) os.Exit(1) From d414fcc32cf1b1a403dc1e870bcbeada95220bf8 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Thu, 3 Jul 2025 11:26:15 +0100 Subject: [PATCH 071/448] refactor: add dockerfile for windows build and make build-binaries (#1720) # Description We want to separate the windows build into 2 steps 1. Build the binaries needed for the final image 2. Build the final image including the binaries built in step 1 For step 1, add a build-binaries task to the Makefile that builds the binaries needed for the final image. For step 2, add a Dockerfile for the windows build that builds the final image including the binaries built in step 1 ## Related Issue ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- Makefile | 4 +++ .../Dockerfile.windows-retina-oss-build | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 controller/Dockerfile.windows-retina-oss-build diff --git a/Makefile b/Makefile index 4b89477c52..210a64505a 100644 --- a/Makefile +++ b/Makefile @@ -346,6 +346,10 @@ all-gen: ## generate all code $(MAKE) proto-gen $(MAKE) go-gen +build-windows-binaries: + GOOS=windows GOARCH=$(GOARCH) go build -v -o /go/bin/retina/captureworkload -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=$(TAG) -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID=$(APP_INSIGHTS_ID)" captureworkload/main.go + GOOS=windows GOARCH=$(GOARCH) go build -x -v -o /go/bin/retina/controller -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=$(TAG) -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID=$(APP_INSIGHTS_ID)" controller/main.go + ##@ Multiplatform manifest-retina-image: ## create a multiplatform manifest for the retina image diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build new file mode 100644 index 0000000000..be4569c473 --- /dev/null +++ b/controller/Dockerfile.windows-retina-oss-build @@ -0,0 +1,27 @@ +# Only applicable for windows images +ARG OS_VERSION=ltsc2022 +# pinned base images + +# mcr.microsoft.com/windows/servercore:ltsc2019 +FROM mcr.microsoft.com/windows/servercore@sha256:6fdf140282a2f809dae9b13fe441635867f0a27c33a438771673b8da8f3348a4 AS ltsc2019 + +# mcr.microsoft.com/windows/servercore:ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:45952938708fbde6ec0b5b94de68bcdec3f8c838be018536b1e9e5bd95e6b943 AS ltsc2022 + +FROM ${OS_VERSION} AS agent-win +ARG GOARCH=amd64 # default to amd64 +ARG GOOS=windows # default to windows +ARG OS_VERSION=ltsc2022 +ARG REPO_PATH +ARG BINARIES_PATH +ENV GOARCH=${GOARCH} +ENV GOOS=${GOOS} +ENV OS_VERSION=${OS_VERSION} +ENV BINARIES_PATH=${BINARIES_PATH} +ENV REPO_PATH=${REPO_PATH} +COPY ${REPO_PATH}/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml +COPY ${REPO_PATH}/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 +COPY ${BINARIES_PATH}/captureworkload.exe captureworkload.exe +COPY ${BINARIES_PATH}/controller.exe controller.exe +ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe +CMD ["controller.exe", "start", "--kubeconfig=.\\kubeconfig"] From 26a533bffc33d48fe91f7e34e04c5627be3d9200 Mon Sep 17 00:00:00 2001 From: Mereta Date: Thu, 3 Jul 2025 14:34:16 +0100 Subject: [PATCH 072/448] chore(pfl): Extend Heartbeat telemetry to accept custom label. (#1712) # Description Extending Heartbeat to accept a list of custom labels. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Testing with custom label ![image](https://github.com/user-attachments/assets/98b2b823-49b9-447e-a3a6-d8743a833335) ![image](https://github.com/user-attachments/assets/98b2b823-49b9-447e-a3a6-d8743a833335) Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: mereta --- pkg/telemetry/noop_telemetry.go | 2 +- pkg/telemetry/telemetry.go | 15 +++++++++++---- pkg/telemetry/telemetry_test.go | 25 +++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/pkg/telemetry/noop_telemetry.go b/pkg/telemetry/noop_telemetry.go index 8391af105c..12fee02381 100644 --- a/pkg/telemetry/noop_telemetry.go +++ b/pkg/telemetry/noop_telemetry.go @@ -23,7 +23,7 @@ func (m NoopTelemetry) StartPerf(functionName string) *PerformanceCounter { func (m NoopTelemetry) StopPerf(counter *PerformanceCounter) { } -func (m NoopTelemetry) Heartbeat(ctx context.Context, heartbeatInterval time.Duration) { +func (m NoopTelemetry) Heartbeat(_ context.Context, _ time.Duration, _ ...func() map[string]string) { } func (m NoopTelemetry) TrackEvent(name string, properties map[string]string) { diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index 0c91f32e67..0cedef23aa 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -48,7 +48,10 @@ var ( type Telemetry interface { StartPerf(name string) *PerformanceCounter StopPerf(counter *PerformanceCounter) - Heartbeat(ctx context.Context, heartbeatInterval time.Duration) + // Heartbeat sends a heartbeat event with system metrics and custom properties. + // funcs are optional functions that return additional properties to be included in the heartbeat event. + // Add custom data with caution as it will increase the size of Heartbeat obejct and may infer storage costs + Heartbeat(ctx context.Context, heartbeatInterval time.Duration, funcs ...func() map[string]string) TrackEvent(name string, properties map[string]string) TrackMetric(name string, value float64, properties map[string]string) TrackTrace(name string, severity contracts.SeverityLevel, properties map[string]string) @@ -167,7 +170,7 @@ func (t *TelemetryClient) trackWarning(err error, msg string) { t.TrackTrace(msg+": "+err.Error(), contracts.Warning, GetEnvironmentProperties()) } -func (t *TelemetryClient) heartbeat(ctx context.Context) { +func (t *TelemetryClient) heartbeat(ctx context.Context, funcs ...func() map[string]string) { kernelVersion, err := KernelVersion(ctx) if err != nil { t.trackWarning(err, "failed to get kernel version") @@ -189,6 +192,10 @@ func (t *TelemetryClient) heartbeat(ctx context.Context) { props["metricscardinality"] = strconv.Itoa(metricscardinality) + for _, f := range funcs { + maps.Copy(props, f()) + } + maps.Copy(props, cpuProps) maps.Copy(props, t.profile.GetMemoryUsage()) t.TrackEvent("heartbeat", props) @@ -352,7 +359,7 @@ func (t *TelemetryClient) StopPerf(counter *PerformanceCounter) { t.TrackMetric(counter.functionName, ms, nil) } -func (t *TelemetryClient) Heartbeat(ctx context.Context, heartbeatInterval time.Duration) { +func (t *TelemetryClient) Heartbeat(ctx context.Context, heartbeatInterval time.Duration, funcs ...func() map[string]string) { ticker := time.NewTicker(heartbeatInterval) // TODOL: make configurable defer ticker.Stop() @@ -361,7 +368,7 @@ func (t *TelemetryClient) Heartbeat(ctx context.Context, heartbeatInterval time. case <-ctx.Done(): return case <-ticker.C: - t.heartbeat(ctx) + t.heartbeat(ctx, funcs...) } } } diff --git a/pkg/telemetry/telemetry_test.go b/pkg/telemetry/telemetry_test.go index 6dfae581db..7eccb09459 100644 --- a/pkg/telemetry/telemetry_test.go +++ b/pkg/telemetry/telemetry_test.go @@ -68,7 +68,8 @@ func TestHeartbeat(t *testing.T) { properties map[string]string } type args struct { - ctx context.Context + ctx context.Context + funcs []func() map[string]string } tests := []struct { name string @@ -84,6 +85,26 @@ func TestHeartbeat(t *testing.T) { }, args: args{ ctx: context.Background(), + funcs: []func() map[string]string{ + func() map[string]string { + return map[string]string{ + "customLabel1": "value1", + "customLabel2": "value2", + } + }, + }, + }, + }, + { + name: "test heartbeat with labels", + fields: fields{ + properties: map[string]string{ + "test": "test", + }, + }, + args: args{ + ctx: context.Background(), + funcs: []func() map[string]string{}, }, }, } @@ -94,7 +115,7 @@ func TestHeartbeat(t *testing.T) { properties: tt.fields.properties, profile: NewNoopPerfProfile(), } - tr.heartbeat(tt.args.ctx) + tr.heartbeat(tt.args.ctx, tt.args.funcs...) }) } } From 13309aea7bf371da50daa86c9c96e27f49e5dd84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:00:02 -0400 Subject: [PATCH 073/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.82.0 to 1.83.0 (#1733) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.82.0 to 1.83.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.82.0&new-version=1.83.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 182c992df4..7f860ef1fe 100644 --- a/go.mod +++ b/go.mod @@ -275,7 +275,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.36.5 github.com/aws/aws-sdk-go-v2/config v1.29.17 github.com/aws/aws-sdk-go-v2/credentials v1.17.70 - github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.83.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 7360e9b2c7..526961cf65 100644 --- a/go.sum +++ b/go.sum @@ -274,8 +274,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 h1:qcLWgdhq45sDM github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17/go.mod h1:M+jkjBFZ2J6DJrjMv2+vkBbuht6kxJYtJiwoVgX4p4U= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 h1:JubM8CGDDFaAOmBrd8CRYNr49ZNgEAiLwGwgNMdS0nw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.83.0 h1:5Y75q0RPQoAbieyOuGLhjV9P3txvYgXv2lg0UwJOfmE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.83.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= From b99d5a27f1c29bd0f5450b94d1cb137bcbd4a47c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:00:42 -0400 Subject: [PATCH 074/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage from 1.8.0 to 1.8.1 (#1730) [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage&package-manager=go_modules&previous-version=1.8.0&new-version=1.8.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7f860ef1fe..31dd220f6b 100644 --- a/go.mod +++ b/go.mod @@ -268,7 +268,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 diff --git a/go.sum b/go.sum index 526961cf65..ac56c38b51 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0/go.mod h1:GE4m0rnnfwLGX0Y9A9A25Zx5N/90jneT5ABevqzhuFQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S6wk65vfC6m3FIxJ+i5QDyN9JWwXI8Hb0Img10hU= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= From 3119094c7de76e9e5eed8c3cd86e0d31bed734b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:00:57 -0400 Subject: [PATCH 075/448] deps: bump github.com/prometheus/common from 0.64.0 to 0.65.0 (#1729) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.64.0 to 0.65.0.
Release notes

Sourced from github.com/prometheus/common's releases.

v0.65.0

What's Changed

New Contributors

Full Changelog: https://github.com/prometheus/common/compare/v0.64.0...v0.65.0

Commits
  • 75c3814 feat: Support negative duration in new function ParseDurationAllowNegative (#...
  • 7bd5fff feat(promslog): add Level() method to get slog.Level (#795)
  • 95acce1 Merge pull request #791 from prometheus/remove-otlptranslator
  • 1de8cfa Remove otlptranslator package
  • 098669c Update common Prometheus files (#789)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/common&package-manager=go_modules&previous-version=0.64.0&new-version=0.65.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 31dd220f6b..a9503cdfee 100644 --- a/go.mod +++ b/go.mod @@ -296,7 +296,7 @@ require ( github.com/onsi/gomega v1.37.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 - github.com/prometheus/common v0.64.0 + github.com/prometheus/common v0.65.0 github.com/safchain/ethtool v0.6.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 diff --git a/go.sum b/go.sum index ac56c38b51..cb57dbb798 100644 --- a/go.sum +++ b/go.sum @@ -1256,8 +1256,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= -github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= From 248dc4e7499ebd99f37342ac8c9bb9f53da19645 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Jul 2025 11:24:59 -0400 Subject: [PATCH 076/448] deps: bump aquasecurity/trivy-action from 0.31.0 to 0.32.0 (#1735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.31.0 to 0.32.0.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.32.0

What's Changed

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.31.0...0.32.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.31.0&new-version=0.32.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index ff420536d4..806b9f223a 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -30,7 +30,7 @@ jobs: echo "TAG=$(make version)" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@76071ef0d7ec797419534a183b498b4d6366cf37 + uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From 0c157d32d70cc5380c66ddc997fe4bc7863346d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:22:45 -0400 Subject: [PATCH 077/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.8.4 to 0.8.5 (#1736) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.8.4 to 0.8.5.
Commits
  • 163f909 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/stora...
  • bbb513c fix: fix error evaluation in AttachDisk (#9040)
  • 7cd6c31 fix: don't change subnet.PrivateEndpointNetworkPolicies setting if set (#9227)
  • 2d6de84 build(deps): bump sigs.k8s.io/cloud-provider-azure/pkg/azclient (#9228)
  • 6179ef6 Skip adding Internet service tag if IP ranges allow all (#9208)
  • 05b4557 build(deps): bump the all group across 1 directory with 9 updates (#9222)
  • e04be51 build(deps): bump github/codeql-action in the all group (#9218)
  • bb7bfb7 build(deps): bump the all group in /pkg/azclient/trace with 2 updates (#9214)
  • 581d537 build(deps): bump sigs.k8s.io/yaml (#9212)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.8.4&new-version=0.8.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a9503cdfee..e1402406f0 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.9.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.4 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.5 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 ) diff --git a/go.sum b/go.sum index cb57dbb798..90a639be55 100644 --- a/go.sum +++ b/go.sum @@ -1969,8 +1969,8 @@ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.4 h1:OJUTH2EYD4tXL3rc9JgZMh0joQX9MEHooZv68mA+k14= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.4/go.mod h1:RzF4KeJQXjHpHJ2gq2t5KqRrTDf5y5+vrHUTLCBunzo= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.5 h1:FXlu6D2crZ7PXkKT8T/5TVsRlPolT+UfEqJEbPgqHGg= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.5/go.mod h1:xStkacaPRfxYyVE4Mlfcx19BVwtMiZKRb1IB4RISagQ= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= From 9da2b366b723fa58270f084ed226f4a5652c4eaa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Jul 2025 11:11:48 -0400 Subject: [PATCH 078/448] deps: bump golang.org/x/sys from 0.33.0 to 0.34.0 (#1739) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.33.0 to 0.34.0.
Commits
  • 751c3c6 unix: add missing NFT_PAYLOAD_* consts on linux
  • 0c740cc unix: update Go to 1.24.3
  • d62d31c unix: update Linux constants and types to v6.14
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sys&package-manager=go_modules&previous-version=0.33.0&new-version=0.34.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e1402406f0..fdcc80c7fa 100644 --- a/go.mod +++ b/go.mod @@ -244,7 +244,7 @@ require ( golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.15.0 - golang.org/x/sys v0.33.0 + golang.org/x/sys v0.34.0 golang.org/x/term v0.32.0 // indirect google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 90a639be55..dbc7e29f4a 100644 --- a/go.sum +++ b/go.sum @@ -1776,8 +1776,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From fd8db689fe88451e70d684c02ab10f024acab6ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Jul 2025 22:02:23 -0400 Subject: [PATCH 079/448] deps: bump golang.org/x/sync from 0.15.0 to 0.16.0 (#1738) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.15.0 to 0.16.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sync&package-manager=go_modules&previous-version=0.15.0&new-version=0.16.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fdcc80c7fa..6d2d501629 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.15.0 + golang.org/x/sync v0.16.0 golang.org/x/sys v0.34.0 golang.org/x/term v0.32.0 // indirect google.golang.org/protobuf v1.36.6 diff --git a/go.sum b/go.sum index dbc7e29f4a..ddd4a90ade 100644 --- a/go.sum +++ b/go.sum @@ -1711,8 +1711,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 03363513a0db10f191defb37b880d43b0fc5ae52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 15:18:41 +0000 Subject: [PATCH 080/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.18.0 to 1.18.1 (#1744) Bumps [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) from 1.18.0 to 1.18.1.
Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/azcore's releases.

sdk/azcore/v1.18.1

1.18.1 (2025-07-10)

Bugs Fixed

  • Fixed incorrect request/response logging try info when logging a request that's being retried.
  • Fixed a data race in ResourceID.String()
Commits
  • 1cfed5a Prepare azcore v1.18.1 for release (#24907)
  • 7315a8e [azservicebus] Fixing bug where you could lose messages in ReceiveAndDelete (...
  • a4fafd7 Prevent race in ResourceID.String() (#24901)
  • 1b078b2 Upgrade TypeSpec emitter packages to latest versions (#24899)
  • 75c5fe4 cosmos: enable support for obtaining feed ranges from a pkrange in a containe...
  • e3693ce [Storage] stg99 preview release prep (#24841)
  • f8192a1 upgrade internal (#24892)
  • e67c80d [Release] sdk/resourcemanager/storageactions/armstorageactions/1.0.0 generati...
  • e9cdbdd [Release] sdk/resourcemanager/purestorageblock/armpurestorageblock/1.0.0 (#24...
  • f2db0f0 Allow an additional retry for IMDS managed identity requests (#24860)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/azcore&package-manager=go_modules&previous-version=1.18.0&new-version=1.18.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6d2d501629..fddd85d660 100644 --- a/go.mod +++ b/go.mod @@ -261,7 +261,7 @@ require ( require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 diff --git a/go.sum b/go.sum index ddd4a90ade..0f7731533e 100644 --- a/go.sum +++ b/go.sum @@ -57,8 +57,8 @@ github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiX github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 h1:Wc1ml6QlJs2BHQ/9Bqu1jiyggbsSjramq2oUmp5WeIo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= From 1267fb26907b7020fc0d9856b11dddad965b9d89 Mon Sep 17 00:00:00 2001 From: Younsung Lee Date: Wed, 16 Jul 2025 01:11:49 +0900 Subject: [PATCH 081/448] feat(hubble): Add `trafficDistribution` field support for Kubernetes 1.31+ (#1686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Add [trafficDistribution](https://kubernetes.io/docs/concepts/services-networking/service/#traffic-distribution) field support to Hubble services (excluding DaemonSet-connected services) with Kubernetes version compatibility check (≥1.31). This provides better performance and reliability than annotation-based [topologyAwareRouting](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/) by being natively integrated into the Service API. ### Changes: - Added trafficDistribution configuration to Hubble Relay and UI services in values.yaml - Updated service templates with conditional rendering based on Kubernetes version - Excluded DaemonSet-connected services (agent, peer) as they use hostNetwork ### Usage Retina administrators can now set hubble.relay.service.trafficDistribution: PreferClose or hubble.ui.service.trafficDistribution: PreferClose in their values to enable topology-aware routing with improved performance characteristics. ## Related Issue - [Comparison with service.kubernetes.io/topology-mode: Auto](https://kubernetes.io/docs/reference/networking/virtual-ips/#comparison-with-service-kubernetes-io-topology-mode-auto): Kubernetes official doc ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ x I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes ### Why trafficDistribution over topologyAwareRouting? The trafficDistribution field is **recommended** over [topologyAwareRouting](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/) annotations as it provides native Kubernetes Service API integration with better performance and reliability characteristics. This field is available in Kubernetes 1.31+ and offers more granular control over traffic routing behavior compared to the annotation-based approach. ```mermaid --- title: topologyAwareRouting vs trafficDistribution --- graph LR A[K8s < 1.31] --> B["`**topologyAwareRouting** Annotation (Legacy)`"] C[K8s ≥ 1.31] --> D["`**trafficDistribution** PreferClose`"] B --Migration--> D B --> F["`Inter AZ DTO Cost Reduction`"] D --> F style D fill:darkorange, color:white style B stroke:red, color:white note["As of Kubernetes 1.31, the trafficDistribution feature has been moved to beta."] style note fill:transparent, stroke:transparent, color:lightgray ``` --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .../helm/retina/templates/hubble-relay/service.yaml | 3 +++ .../helm/retina/templates/hubble-ui/service.yaml | 3 +++ .../manifests/controller/helm/retina/values.yaml | 12 ++++++++++++ 3 files changed, 18 insertions(+) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/service.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/service.yaml index fc13c90165..cb82b4b97d 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/service.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/hubble-relay/service.yaml @@ -14,6 +14,9 @@ metadata: app.kubernetes.io/part-of: retina spec: type: {{ .Values.hubble.relay.service.type | quote }} + {{- if and .Values.hubble.relay.service.trafficDistribution (semverCompare ">=1.31-0" .Capabilities.KubeVersion.GitVersion) }} + trafficDistribution: {{ .Values.hubble.relay.service.trafficDistribution }} + {{- end }} selector: k8s-app: hubble-relay ports: diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/service.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/service.yaml index a820b3420b..251415e689 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/service.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/service.yaml @@ -19,6 +19,9 @@ metadata: app.kubernetes.io/part-of: cilium spec: type: {{ .Values.hubble.ui.service.type | quote }} + {{- if and .Values.hubble.ui.service.trafficDistribution (semverCompare ">=1.31-0" .Capabilities.KubeVersion.GitVersion) }} + trafficDistribution: {{ .Values.hubble.ui.service.trafficDistribution }} + {{- end }} selector: k8s-app: hubble-ui ports: diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 360081f1a1..998692b456 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -504,6 +504,12 @@ hubble: type: ClusterIP # --- The port to use when the service type is set to NodePort. nodePort: 31234 + # --- trafficDistribution field for service load balancing behavior. + # Valid values: PreferClose + # Provides better performance and reliability than annotation-based topologyAwareRouting + # by being built into the Service API and offering more predictable routing behavior. + # See https://kubernetes.io/docs/concepts/services-networking/service/#traffic-distribution + trafficDistribution: "" # -- Host to listen to. Specify an empty string to bind to all the interfaces. listenHost: "" @@ -779,6 +785,12 @@ hubble: type: ClusterIP # --- The port to use when the service type is set to NodePort. nodePort: 31235 + # --- trafficDistribution field for service load balancing behavior. + # Valid values: PreferClose + # Provides better performance and reliability than annotation-based topologyAwareRouting + # by being built into the Service API and offering more predictable routing behavior. + # See https://kubernetes.io/docs/concepts/services-networking/service/#traffic-distribution + trafficDistribution: "" # -- Defines base url prefix for all hubble-ui http requests. # It needs to be changed in case if ingress for hubble-ui is configured under some sub-path. From ba36848028f1591e2f40c8826da250eb316d0aa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 16:12:37 +0000 Subject: [PATCH 082/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.8.5 to 0.8.6 (#1746) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.8.5 to 0.8.6.
Commits
  • 5326324 build(deps): bump the all group in /pkg/azclient with 4 updates (#9262)
  • 6f78c1d build(deps): bump the all group in /pkg/azclient/cache with 2 updates (#9261)
  • 28800f5 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore (#9256)
  • 0cebf8d build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore (#9253)
  • 481e2e6 fix: migrate interface client operations from NetworkClientFactory to… (#9250)
  • 30a227f build(deps): bump sigs.k8s.io/cloud-provider-azure/pkg/azclient (#9248)
  • 101bc26 build(deps): bump the all group with 2 updates (#9246)
  • 9430ddf build(deps): bump sigs.k8s.io/cloud-provider-azure/pkg/azclient (#9244)
  • 38430f0 build(deps): bump the all group with 3 updates (#9240)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.8.5&new-version=0.8.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index fddd85d660..4ff04bbb9f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.9.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.5 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 ) @@ -210,11 +210,11 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.39.0 // indirect + golang.org/x/crypto v0.40.0 // indirect golang.org/x/mod v0.25.0 // indirect - golang.org/x/text v0.26.0 // indirect + golang.org/x/text v0.27.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/tools v0.34.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect @@ -241,11 +241,11 @@ require ( github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.41.0 // indirect + golang.org/x/net v0.42.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.16.0 golang.org/x/sys v0.34.0 - golang.org/x/term v0.32.0 // indirect + golang.org/x/term v0.33.0 // indirect google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 diff --git a/go.sum b/go.sum index 0f7731533e..5ec1c627cd 100644 --- a/go.sum +++ b/go.sum @@ -1623,8 +1623,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1692,8 +1692,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= @@ -1788,8 +1788,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1801,8 +1801,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1837,8 +1837,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= 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= @@ -1969,8 +1969,8 @@ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.5 h1:FXlu6D2crZ7PXkKT8T/5TVsRlPolT+UfEqJEbPgqHGg= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.5/go.mod h1:xStkacaPRfxYyVE4Mlfcx19BVwtMiZKRb1IB4RISagQ= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6 h1:eihqzFmOkaHB27UsvaGrP4FBH1q00rUwNCEedmu8S+4= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6/go.mod h1:4OImMMFi7wMfpcUcVrUvXO46mi21ndTTuRtQGzuEMD4= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= From 95a48c1280a0db96deb47a086847dce82ebec790 Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Thu, 17 Jul 2025 15:02:53 -0700 Subject: [PATCH 083/448] fix(packetparser): Fix under reporting of TCP flags and packet metrics, improve scalability (#1665) # Description Previously `packetparser` in `high` `dataAggregationLevel` would report (mostly) every single packet since important flags were observed over the lifetime of the connection. This changes that behavior to only observe the important flags on individual packets and report when necessary. This will mean less packets are reported. However, it also adds back weighting for bytes, packets, and TCP flags so that metrics remain accurate versus before. I also noticed the current docs for the TCP flags metrics are inaccurate, we only report a subset of the supported flags. Not sure if this is intentional, however supporting more flags will put more memory pressure on both conntrack as well as performance pressure on packet reporting. With sampling in place, this should be more than worth it but there may be repercussions for the performance of `low` `dataAggregationLevel`. ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed eBPF objects compile and load as expected. # `main` Branch tcpflags main prometheus packets retina main prometheus bytes retina main # This Branch tcpflags patched prometheus packets retina patched prometheus bytes retina patched ## Additional Notes https://github.com/microsoft/retina/pull/1628 will be a follow-up to this to add additional sampling functionality. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- pkg/metrics/metrics.go | 6 + pkg/metrics/types.go | 3 + pkg/module/metrics/forward.go | 4 +- pkg/module/metrics/latency_test.go | 8 +- pkg/module/metrics/tcpflags.go | 46 +- pkg/plugin/conntrack/_cprog/conntrack.c | 284 ++- pkg/plugin/conntrack/_cprog/conntrack.h | 1 + pkg/plugin/conntrack/conntrack_bpfel_arm64.go | 32 +- pkg/plugin/conntrack/conntrack_bpfel_x86.go | 32 +- pkg/plugin/packetparser/_cprog/packetparser.c | 11 +- .../packetparser/packetparser_bpfel_arm64.go | 59 +- .../packetparser/packetparser_bpfel_x86.go | 59 +- pkg/plugin/packetparser/packetparser_linux.go | 21 + pkg/plugin/packetparser/types_linux.go | 1 + pkg/plugin/tcpretrans/tcpretrans_linux.go | 13 +- pkg/utils/flow_utils.go | 69 +- pkg/utils/metadata_linux.pb.go | 99 +- pkg/utils/metadata_linux.proto | 5 + pkg/utils/metadata_windows.pb.go | 1826 +++++++++-------- pkg/utils/metadata_windows.proto | 5 + 20 files changed, 1568 insertions(+), 1016 deletions(-) diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index ea9e2e5a9d..9169a08d8d 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -188,6 +188,12 @@ func InitializeMetrics() { ConntrackTotalConnectionsDescription, ) + ParsedPacketsCounter = exporter.CreatePrometheusCounterVecForControlPlaneMetric( + exporter.DefaultRegistry, + parsedPacketsCounterName, + parsedPacketsCounterDescription, + ) + isInitialized = true metricsLogger.Info("Metrics initialized") } diff --git a/pkg/metrics/types.go b/pkg/metrics/types.go index 486698390a..0803f62a71 100644 --- a/pkg/metrics/types.go +++ b/pkg/metrics/types.go @@ -12,6 +12,7 @@ const ( // Control plane metrics pluginManagerFailedToReconcileCounterName = "plugin_manager_failed_to_reconcile" lostEventsCounterName = "lost_events_counter" + parsedPacketsCounterName = "parsed_packets_counter" // Windows hnsStats = "windows_hns_stats" @@ -43,6 +44,7 @@ const ( // Control plane metrics pluginManagerFailedToReconcileCounterDescription = "Number of times the plugin manager failed to reconcile the plugins" lostEventsCounterDescription = "Number of events lost in control plane" + parsedPacketsCounterDescription = "Number of packets parsed by the packetparser plugin" // Conntrack metrics ConntrackPacketTxDescription = "Number of tx packets" @@ -90,6 +92,7 @@ var ( // Control Plane Metrics PluginManagerFailedToReconcileCounter CounterVec LostEventsCounter CounterVec + ParsedPacketsCounter CounterVec // DNS Metrics. DNSRequestCounter CounterVec diff --git a/pkg/module/metrics/forward.go b/pkg/module/metrics/forward.go index 5044ab4c1c..9ed694b2f3 100644 --- a/pkg/module/metrics/forward.go +++ b/pkg/module/metrics/forward.go @@ -170,8 +170,8 @@ func (f *ForwardMetrics) processLocalCtxFlow(flow *v1.Flow) { func (f *ForwardMetrics) update(fl *v1.Flow, labels []string) { switch f.metricName { case utils.ForwardPacketsGaugeName: - f.forwardMetric.WithLabelValues(labels...).Inc() + f.forwardMetric.WithLabelValues(labels...).Add(float64(utils.PreviouslyObservedPackets(fl) + 1)) case utils.ForwardBytesGaugeName: - f.forwardMetric.WithLabelValues(labels...).Add(float64(utils.PacketSize(fl))) + f.forwardMetric.WithLabelValues(labels...).Add(float64(utils.PacketSize(fl) + utils.PreviouslyObservedBytes(fl))) } } diff --git a/pkg/module/metrics/latency_test.go b/pkg/module/metrics/latency_test.go index fcdbfee87c..79195eecd0 100644 --- a/pkg/module/metrics/latency_test.go +++ b/pkg/module/metrics/latency_test.go @@ -124,7 +124,7 @@ func TestProcessFlow(t *testing.T) { f1 := utils.ToFlow(l, t1, apiSeverIp, nodeIp, 80, 443, 6, 3, 0) metaf1 := &utils.RetinaMetadata{} utils.AddTCPID(metaf1, 1234) - utils.AddTCPFlags(f1, 1, 0, 0, 0, 0, 0) + utils.AddTCPFlags(f1, 1, 0, 0, 0, 0, 0, 0, 0, 0) utils.AddRetinaMetadata(f1, metaf1) f1.Destination = &flow.Endpoint{ PodName: "kubernetes-apiserver", @@ -134,7 +134,7 @@ func TestProcessFlow(t *testing.T) { f2 := utils.ToFlow(l, t2, nodeIp, apiSeverIp, 443, 80, 6, 2, 0) metaf2 := &utils.RetinaMetadata{} utils.AddTCPID(metaf2, 1234) - utils.AddTCPFlags(f2, 1, 1, 0, 0, 0, 0) + utils.AddTCPFlags(f2, 1, 1, 0, 0, 0, 0, 0, 0, 0) utils.AddRetinaMetadata(f2, metaf2) f2.Source = &flow.Endpoint{ PodName: "kubernetes-apiserver", @@ -147,9 +147,9 @@ func TestProcessFlow(t *testing.T) { * Test case 2: Existing TCP connection. */ // Node -> Api server. - utils.AddTCPFlags(f1, 1, 0, 0, 0, 0, 0) + utils.AddTCPFlags(f1, 1, 0, 0, 0, 0, 0, 0, 0, 0) // Api server -> Node. - utils.AddTCPFlags(f2, 0, 1, 0, 0, 0, 0) + utils.AddTCPFlags(f2, 0, 1, 0, 0, 0, 0, 0, 0, 0) // Process flow. lm.ProcessFlow(f1) lm.ProcessFlow(f2) diff --git a/pkg/module/metrics/tcpflags.go b/pkg/module/metrics/tcpflags.go index 02c8eb539a..c6a24a8635 100644 --- a/pkg/module/metrics/tcpflags.go +++ b/pkg/module/metrics/tcpflags.go @@ -65,6 +65,27 @@ func (t *TCPMetrics) getLabels() []string { return labels } +func combineFlagsWithPrevious(flags []string, flow *v1.Flow) map[string]uint32 { + var combinedFlags map[string]uint32 + + previous := utils.PreviouslyObservedTCPFlags(flow) + if previous != nil { + combinedFlags = previous + } else { + combinedFlags = map[string]uint32{} + } + + for _, flag := range flags { + if _, ok := combinedFlags[flag]; !ok { + combinedFlags[flag] = 1 + } else { + combinedFlags[flag]++ + } + } + + return combinedFlags +} + func (t *TCPMetrics) ProcessFlow(flow *v1.Flow) { if flow == nil { return @@ -100,11 +121,11 @@ func (t *TCPMetrics) ProcessFlow(flow *v1.Flow) { dstLabels = t.dstCtx.getValues(flow) } - for _, flag := range flags { + for flag, count := range combineFlagsWithPrevious(flags, flow) { labels := append([]string{flag}, srcLabels...) labels = append(labels, dstLabels...) - t.tcpFlagsMetrics.WithLabelValues(labels...).Inc() - t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels)) + t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) + t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) } } @@ -113,20 +134,23 @@ func (t *TCPMetrics) processLocalCtxFlow(flow *v1.Flow, flags []string) { if labelValuesMap == nil { return } + + combinedFlags := combineFlagsWithPrevious(flags, flow) + // Ingress values if l := len(labelValuesMap[ingress]); l > 0 { - for _, flag := range flags { + for flag, count := range combinedFlags { labels := append([]string{flag}, labelValuesMap[ingress]...) - t.tcpFlagsMetrics.WithLabelValues(labels...).Inc() - t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels)) + t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) + t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) } } if l := len(labelValuesMap[egress]); l > 0 { - for _, flag := range flags { + for flag, count := range combinedFlags { labels := append([]string{flag}, labelValuesMap[egress]...) - t.tcpFlagsMetrics.WithLabelValues(labels...).Inc() - t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels)) + t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) + t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) } } } @@ -171,6 +195,10 @@ func (t *TCPMetrics) getFlagValues(flags *v1.TCPFlags) []string { f = append(f, utils.CWR) } + if flags.GetNS() { + f = append(f, utils.NS) + } + return f } diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c index 73761865c9..38fc62305c 100644 --- a/pkg/plugin/conntrack/_cprog/conntrack.c +++ b/pkg/plugin/conntrack/_cprog/conntrack.c @@ -31,23 +31,53 @@ struct conntrackmetadata { __u32 packets_rx_count; }; +/** + * The structure representing the count of observed TCP flags. + * To observe new flags, they should be added to this structure and _ct_record_tcp_flags updated. + */ +struct tcpflagscount +{ + __u32 syn; + __u32 ack; + __u32 fin; + __u32 rst; + __u32 psh; + __u32 urg; + __u32 ece; + __u32 cwr; + __u32 ns; +}; + struct packet { - __u64 t_nsec; // timestamp in nanoseconds - __u32 bytes; // packet size in bytes - __u32 src_ip; - __u32 dst_ip; - __u16 src_port; - __u16 dst_port; - struct tcpmetadata tcp_metadata; // TCP metadata - __u8 observation_point; - __u8 traffic_direction; - __u8 proto; - __u8 flags; // For TCP packets, this is the TCP flags. For UDP packets, this is will always be 1 for conntrack purposes. - bool is_reply; + __u64 t_nsec; // timestamp in nanoseconds + __u32 bytes; // packet size in bytes + __u32 src_ip; + __u32 dst_ip; + __u16 src_port; + __u16 dst_port; + struct tcpmetadata tcp_metadata; // TCP metadata + __u8 observation_point; + __u8 traffic_direction; + __u8 proto; + __u16 flags; // For TCP packets, this is the TCP flags. For UDP packets, this is will always be 1 for conntrack purposes. + bool is_reply; + __u32 previously_observed_packets; // When sampling, this is the number of observed packets since the last report. + __u32 previously_observed_bytes; // When sampling, this is the number of observed bytes since the last report. + struct tcpflagscount previously_observed_flags; // When sampling, this is the previously observed TCP flags since the last report. struct conntrackmetadata conntrack_metadata; }; +/** + * The structure representing whether or not to report a packet and associated metadata. + */ +struct packetreport +{ + __u32 previously_observed_packets; + __u32 previously_observed_bytes; + struct tcpflagscount previously_observed_flags; + bool report; +}; /** * The structure representing an ipv4 5-tuple key in the connection tracking map. @@ -59,6 +89,7 @@ struct ct_v4_key { __u16 dst_port; __u8 proto; }; + /** * The structure representing a connection in the connection tracking map. */ @@ -69,6 +100,21 @@ struct ct_entry { */ __u32 last_report_tx_dir; __u32 last_report_rx_dir; + /** + * bytes_seen_since_last_report_*_dir stores the number of bytes observed since the last packet event was reported. + */ + __u32 bytes_seen_since_last_report_tx_dir; + __u32 bytes_seen_since_last_report_rx_dir; + /** + * packets_seen_since_last_report_*_dir stores the number of packets observed since the last packet event was reported. + */ + __u32 packets_seen_since_last_report_tx_dir; + __u32 packets_seen_since_last_report_rx_dir; + /** + * flags_seen_since_last_report_*_dir stores the number of TCP flags observed since the last packet event was reported. + */ + struct tcpflagscount flags_seen_since_last_report_tx_dir; + struct tcpflagscount flags_seen_since_last_report_rx_dir; /** * traffic_direction indicates the direction of the connection in relation to the host. * If the connection is initiated from within the host, the traffic_direction is egress. Otherwise, the traffic_direction is ingress. @@ -95,6 +141,62 @@ struct { __uint(pinning, LIBBPF_PIN_BY_NAME); // needs pinning so this can be access from other processes .i.e debug cli } retina_conntrack SEC(".maps"); +/** + * Helper function to update the count of observed TCP flags. + * @arg flags The observed flags. + * @arg count The TCP flag count to update. + */ +static inline void _ct_record_tcp_flags(__u8 flags, struct tcpflagscount *count) { + if (!count) { + return; + } + if (flags & TCP_SYN) { + if (count->syn < UINT32_MAX) { + count->syn += 1; + } + } + if (flags & TCP_ACK) { + if (count->ack < UINT32_MAX) { + count->ack += 1; + } + } + if (flags & TCP_FIN) { + if (count->fin < UINT32_MAX) { + count->fin += 1; + } + } + if (flags & TCP_RST) { + if (count->rst < UINT32_MAX) { + count->rst += 1; + } + } + if (flags & TCP_PSH) { + if (count->psh < UINT32_MAX) { + count->psh += 1; + } + } + if (flags & TCP_URG) { + if (count->urg < UINT32_MAX) { + count->urg += 1; + } + } + if (flags & TCP_ECE) { + if (count->ece < UINT32_MAX) { + count->ece += 1; + } + } + if (flags & TCP_CWR) { + if (count->cwr < UINT32_MAX) { + count->cwr += 1; + } + } + if (flags & TCP_NS) { + if (count->ns < UINT32_MAX) { + count->ns += 1; + } + } +} + /** * Helper function to reverse a key. * @arg reverse_key The key to store the reversed key. @@ -144,9 +246,13 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru if(is_reply) { new_value.flags_seen_rx_dir = p->flags; new_value.last_report_rx_dir = now; + new_value.bytes_seen_since_last_report_rx_dir = 0; + new_value.packets_seen_since_last_report_rx_dir = 0; } else { new_value.flags_seen_tx_dir = p->flags; new_value.last_report_tx_dir = now; + new_value.bytes_seen_since_last_report_tx_dir = 0; + new_value.packets_seen_since_last_report_tx_dir = 0; } new_value.is_direction_unknown = false; new_value.traffic_direction = _ct_get_traffic_direction(observation_point); @@ -187,6 +293,8 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c new_value.eviction_time = now + CT_CONNECTION_LIFETIME_NONTCP; new_value.flags_seen_tx_dir = p->flags; new_value.last_report_tx_dir = now; + new_value.bytes_seen_since_last_report_tx_dir = 0; + new_value.packets_seen_since_last_report_tx_dir = 0; new_value.traffic_direction = _ct_get_traffic_direction(observation_point); #ifdef ENABLE_CONNTRACK_METRICS new_value.conntrack_metadata.packets_tx_count = 1; @@ -240,6 +348,8 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c p->is_reply = true; new_value.flags_seen_rx_dir = p->flags; new_value.last_report_rx_dir = now; + new_value.bytes_seen_since_last_report_rx_dir = 0; + new_value.packets_seen_since_last_report_rx_dir = 0; #ifdef ENABLE_CONNTRACK_METRICS new_value.conntrack_metadata.bytes_rx_count = p->bytes; new_value.conntrack_metadata.packets_rx_count = 1; @@ -249,6 +359,8 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c p->is_reply = false; new_value.flags_seen_tx_dir = p->flags; new_value.last_report_tx_dir = now; + new_value.bytes_seen_since_last_report_tx_dir = 0; + new_value.packets_seen_since_last_report_tx_dir = 0; #ifdef ENABLE_CONNTRACK_METRICS new_value.conntrack_metadata.bytes_tx_count = p->bytes; new_value.conntrack_metadata.packets_tx_count = 1; @@ -269,14 +381,17 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c * @arg reverse_key The reverse key to be used to handle the connection. * @arg observation_point The point in the network stack where the packet is observed. */ -static __always_inline bool _ct_handle_new_connection(struct packet *p, struct ct_v4_key key, struct ct_v4_key reverse_key, __u8 observation_point) { +static __always_inline struct packetreport _ct_handle_new_connection(struct packet *p, struct ct_v4_key key, struct ct_v4_key reverse_key, __u8 observation_point) { + struct packetreport report; + __builtin_memset(&report, 0, sizeof(struct packetreport)); if (key.proto & IPPROTO_TCP) { - return _ct_handle_tcp_connection(p, key, reverse_key, observation_point); + report.report = _ct_handle_tcp_connection(p, key, reverse_key, observation_point); } else if (key.proto & IPPROTO_UDP) { - return _ct_handle_udp_connection(p, key, observation_point); + report.report = _ct_handle_udp_connection(p, key, observation_point); } else { - return false; // We are not interested in other protocols. + report.report = false; // We are not interested in other protocols. } + return report; } /** @@ -285,40 +400,69 @@ static __always_inline bool _ct_handle_new_connection(struct packet *p, struct c * @arg entry The entry of the connection in Retina's conntrack map. * @arg flags The flags of the packet. * @arg direction The direction of the packet in relation to the connection. - * Returns true if the packet should be reported to userspace. False otherwise. + * @arg bytes The size of the packet in bytes. + * Returns a packetreport struct representing if the packet should be reported to userspace. */ -static __always_inline bool _ct_should_report_packet(struct ct_v4_key *key, struct ct_entry *entry, __u8 flags, __u8 direction) { +static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4_key *key, struct ct_entry *entry, __u8 flags, __u8 direction, __u32 bytes) { + struct packetreport report; + __builtin_memset(&report, 0, sizeof(struct packetreport)); + report.report = false; + // Check for null parameters. if (!entry || !key) { - return false; - } - - __u64 now = bpf_mono_now(); - __u32 eviction_time = READ_ONCE(entry->eviction_time); - // Check if the connection timed out - if (now >= eviction_time) { - bpf_map_delete_elem(&retina_conntrack, key); - return true; // Report the last packet received before deletion + return report; } // Get direction-specific data __u8 seen_flags; __u32 last_report; + __u32 packets_seen; + __u32 bytes_seen; if (direction == CT_PACKET_DIR_TX) { seen_flags = READ_ONCE(entry->flags_seen_tx_dir); last_report = READ_ONCE(entry->last_report_tx_dir); + bytes_seen = READ_ONCE(entry->bytes_seen_since_last_report_tx_dir); + packets_seen = READ_ONCE(entry->packets_seen_since_last_report_tx_dir); + __builtin_memcpy(&report.previously_observed_flags, &entry->flags_seen_since_last_report_tx_dir, sizeof(struct tcpflagscount)); } else { seen_flags = READ_ONCE(entry->flags_seen_rx_dir); last_report = READ_ONCE(entry->last_report_rx_dir); + bytes_seen = READ_ONCE(entry->bytes_seen_since_last_report_rx_dir); + packets_seen = READ_ONCE(entry->packets_seen_since_last_report_rx_dir); + __builtin_memcpy(&report.previously_observed_flags, &entry->flags_seen_since_last_report_rx_dir, sizeof(struct tcpflagscount)); + } + + report.previously_observed_bytes = bytes_seen; + report.previously_observed_packets = packets_seen; + + // Check for overflow + if (bytes_seen <= UINT32_MAX-bytes) { + bytes_seen += bytes; + } + + if (packets_seen <= UINT32_MAX-1) { + packets_seen += 1; + } + + __u64 now = bpf_mono_now(); + __u32 eviction_time = READ_ONCE(entry->eviction_time); + + // Check if the connection timed out + if (now >= eviction_time) { + bpf_map_delete_elem(&retina_conntrack, key); + report.report = true; + return report; // Report the last packet received before deletion } + __u8 packet_flags = flags; + // OR the seen flags with the new flags flags |= seen_flags; __u8 protocol = key->proto; - + // Handle connection state updates and reporting conditions bool should_report = false; - + // TCP-specific state management if (protocol == IPPROTO_TCP) { // Handle TCP connection termination states @@ -330,11 +474,19 @@ static __always_inline bool _ct_should_report_packet(struct ct_v4_key *key, stru (entry->flags_seen_tx_dir & TCP_FIN) && (entry->flags_seen_rx_dir & TCP_FIN)) { bpf_map_delete_elem(&retina_conntrack, key); - return true; // Report final ACK before connection removal + report.report = true; + return report; // Report final ACK before connection removal + } + + // If RST is seen, delete connection immediately + if (flags & TCP_RST) { + bpf_map_delete_elem(&retina_conntrack, key); + report.report = true; + return report; // Report RST before connection removal } // Update FIN flag status in the appropriate direction - if (flags & TCP_FIN) { + if (packet_flags & TCP_FIN) { if (direction == CT_PACKET_DIR_TX) { entry->flags_seen_tx_dir |= TCP_FIN; } else { @@ -342,26 +494,20 @@ static __always_inline bool _ct_should_report_packet(struct ct_v4_key *key, stru } should_report = true; // Always report FIN packets } - - // If FIN seen in both directions, transition to TIME_WAIT state - if ((entry->flags_seen_tx_dir & TCP_FIN) && (entry->flags_seen_rx_dir & TCP_FIN)) { - WRITE_ONCE(entry->eviction_time, now + CT_TIME_WAIT_TIMEOUT_TCP); - return true; // Report transition to TIME_WAIT - } - // If RST is seen, delete connection immediately - if (flags & TCP_RST) { - bpf_map_delete_elem(&retina_conntrack, key); - return true; // Report RST before connection removal - } - // Always report important TCP control flags - if (flags & (TCP_SYN | TCP_URG | TCP_ECE | TCP_CWR)) { + if (packet_flags & (TCP_SYN | TCP_URG | TCP_ECE | TCP_CWR)) { should_report = true; } - - // Extend TCP connection lifetime - WRITE_ONCE(entry->eviction_time, now + CT_CONNECTION_LIFETIME_TCP); + + // If FIN seen in both directions, transition to TIME_WAIT state + if ((entry->flags_seen_tx_dir & TCP_FIN) && (entry->flags_seen_rx_dir & TCP_FIN)) { + WRITE_ONCE(entry->eviction_time, now + CT_TIME_WAIT_TIMEOUT_TCP); + should_report = true; // Report transition to TIME_WAIT + } else { + // Extend TCP connection lifetime + WRITE_ONCE(entry->eviction_time, now + CT_CONNECTION_LIFETIME_TCP); + } } else if (protocol == IPPROTO_UDP) { // Extend UDP/other connection lifetime WRITE_ONCE(entry->eviction_time, now + CT_CONNECTION_LIFETIME_NONTCP); @@ -372,31 +518,56 @@ static __always_inline bool _ct_should_report_packet(struct ct_v4_key *key, stru // 2. New flags have appeared, or // 3. Reporting interval has elapsed if (should_report || flags != seen_flags || now - last_report >= CT_REPORT_INTERVAL) { + report.report = true; // Update the connection's state if (direction == CT_PACKET_DIR_TX) { WRITE_ONCE(entry->flags_seen_tx_dir, flags); WRITE_ONCE(entry->last_report_tx_dir, now); + WRITE_ONCE(entry->bytes_seen_since_last_report_tx_dir, 0); + WRITE_ONCE(entry->packets_seen_since_last_report_tx_dir, 0); + __builtin_memset(&entry->flags_seen_since_last_report_tx_dir, 0, sizeof(struct tcpflagscount)); } else { WRITE_ONCE(entry->flags_seen_rx_dir, flags); WRITE_ONCE(entry->last_report_rx_dir, now); + WRITE_ONCE(entry->bytes_seen_since_last_report_rx_dir, 0); + WRITE_ONCE(entry->packets_seen_since_last_report_rx_dir, 0); + __builtin_memset(&entry->flags_seen_since_last_report_rx_dir, 0, sizeof(struct tcpflagscount)); + } + return report; + } else { + struct tcpflagscount newcount; + __builtin_memcpy(&newcount, &report.previously_observed_flags, sizeof(struct tcpflagscount)); + _ct_record_tcp_flags(packet_flags, &newcount); + if (direction == CT_PACKET_DIR_TX) { + WRITE_ONCE(entry->bytes_seen_since_last_report_tx_dir, bytes_seen); + WRITE_ONCE(entry->packets_seen_since_last_report_tx_dir, packets_seen); + __builtin_memcpy(&entry->flags_seen_since_last_report_tx_dir, &newcount, sizeof(struct tcpflagscount)); + } else { + WRITE_ONCE(entry->bytes_seen_since_last_report_rx_dir, bytes_seen); + WRITE_ONCE(entry->packets_seen_since_last_report_rx_dir, packets_seen); + __builtin_memcpy(&entry->flags_seen_since_last_report_rx_dir, &newcount, sizeof(struct tcpflagscount)); } - return true; } - return false; + return report; } /** * Process a packet and update the connection tracking map. * @arg *p pointer to the packet to be processed. * @arg observation_point The point in the network stack where the packet is observed. - * Returns true if the packet should be report to userspace. False otherwise. + * Returns a packetreport struct representing if the packet should be reported to userspace. */ -static __always_inline __attribute__((unused)) bool ct_process_packet(struct packet *p, __u8 observation_point) { - +static __always_inline __attribute__((unused)) struct packetreport ct_process_packet(struct packet *p, __u8 observation_point) { if (!p) { - return false; + struct packetreport report; + __builtin_memset(&report, 0, sizeof(struct packetreport)); + report.report = false; + report.previously_observed_packets = 0; + report.previously_observed_bytes = 0; + return report; } + // Create a new key for the send direction. struct ct_v4_key key; __builtin_memset(&key, 0, sizeof(struct ct_v4_key)); @@ -405,6 +576,7 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac key.src_port = p->src_port; key.dst_port = p->dst_port; key.proto = p->proto; + // Lookup the connection in the map. struct ct_entry *entry = bpf_map_lookup_elem(&retina_conntrack, &key); @@ -420,7 +592,7 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac // Update packet's conntract metadata. __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS - return _ct_should_report_packet(&key, entry, p->flags, CT_PACKET_DIR_TX); + return _ct_should_report_packet(&key, entry, p->flags, CT_PACKET_DIR_TX, p->bytes); } // The connection is not found in the send direction. Check the reply direction by reversing the key. @@ -442,9 +614,9 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac // Update packet's conntract metadata. __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS - return _ct_should_report_packet(&reverse_key, entry, p->flags, CT_PACKET_DIR_RX); + return _ct_should_report_packet(&reverse_key, entry, p->flags, CT_PACKET_DIR_RX, p->bytes); } // If the connection is still not found, the connection is new. return _ct_handle_new_connection(p, key, reverse_key, observation_point); -} +} \ No newline at end of file diff --git a/pkg/plugin/conntrack/_cprog/conntrack.h b/pkg/plugin/conntrack/_cprog/conntrack.h index 490736648c..0de6018180 100644 --- a/pkg/plugin/conntrack/_cprog/conntrack.h +++ b/pkg/plugin/conntrack/_cprog/conntrack.h @@ -38,6 +38,7 @@ #define TCP_URG 0x20 #define TCP_ECE 0x40 #define TCP_CWR 0x80 +#define TCP_NS 0x100 #define CT_PACKET_DIR_TX 0x00 #define CT_PACKET_DIR_RX 0x01 diff --git a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go index 0cfed44cf9..3a542cef6e 100644 --- a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go +++ b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go @@ -13,9 +13,35 @@ import ( ) type conntrackCtEntry struct { - EvictionTime uint32 - LastReportTxDir uint32 - LastReportRxDir uint32 + EvictionTime uint32 + LastReportTxDir uint32 + LastReportRxDir uint32 + BytesSeenSinceLastReportTxDir uint32 + BytesSeenSinceLastReportRxDir uint32 + PacketsSeenSinceLastReportTxDir uint32 + PacketsSeenSinceLastReportRxDir uint32 + FlagsSeenSinceLastReportTxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } + FlagsSeenSinceLastReportRxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } TrafficDirection uint8 FlagsSeenTxDir uint8 FlagsSeenRxDir uint8 diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.go b/pkg/plugin/conntrack/conntrack_bpfel_x86.go index a3522e44de..14a95f49f4 100644 --- a/pkg/plugin/conntrack/conntrack_bpfel_x86.go +++ b/pkg/plugin/conntrack/conntrack_bpfel_x86.go @@ -13,9 +13,35 @@ import ( ) type conntrackCtEntry struct { - EvictionTime uint32 - LastReportTxDir uint32 - LastReportRxDir uint32 + EvictionTime uint32 + LastReportTxDir uint32 + LastReportRxDir uint32 + BytesSeenSinceLastReportTxDir uint32 + BytesSeenSinceLastReportRxDir uint32 + PacketsSeenSinceLastReportTxDir uint32 + PacketsSeenSinceLastReportRxDir uint32 + FlagsSeenSinceLastReportTxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } + FlagsSeenSinceLastReportRxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } TrafficDirection uint8 FlagsSeenTxDir uint8 FlagsSeenRxDir uint8 diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c index 40ec8fb03e..07256867fb 100644 --- a/pkg/plugin/packetparser/_cprog/packetparser.c +++ b/pkg/plugin/packetparser/_cprog/packetparser.c @@ -209,16 +209,23 @@ static void parse(struct __sk_buff *skb, __u8 obs) #endif // ENABLE_CONNTRACK_METRICS // Process the packet in ct - bool report __attribute__((unused)); + struct packetreport report __attribute__((unused)); report = ct_process_packet(&p, obs); + #ifdef DATA_AGGREGATION_LEVEL // If the data aggregation level is low, always send the packet to the perf buffer. #if DATA_AGGREGATION_LEVEL == DATA_AGGREGATION_LEVEL_LOW + p.previously_observed_packets = 0; + p.previously_observed_bytes = 0; + __builtin_memset(&p.previously_observed_flags, 0, sizeof(struct tcpflagscount)); bpf_perf_event_output(skb, &retina_packetparser_events, BPF_F_CURRENT_CPU, &p, sizeof(p)); return; // If the data aggregation level is high, only send the packet to the perf buffer if it needs to be reported. #elif DATA_AGGREGATION_LEVEL == DATA_AGGREGATION_LEVEL_HIGH - if (report) { + if (report.report) { + p.previously_observed_packets = report.previously_observed_packets; + p.previously_observed_bytes = report.previously_observed_bytes; + p.previously_observed_flags = report.previously_observed_flags; bpf_perf_event_output(skb, &retina_packetparser_events, BPF_F_CURRENT_CPU, &p, sizeof(p)); } #endif diff --git a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go index df05ffdcac..3ce8c9a4c8 100644 --- a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go +++ b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go @@ -13,9 +13,35 @@ import ( ) type packetparserCtEntry struct { - EvictionTime uint32 - LastReportTxDir uint32 - LastReportRxDir uint32 + EvictionTime uint32 + LastReportTxDir uint32 + LastReportRxDir uint32 + BytesSeenSinceLastReportTxDir uint32 + BytesSeenSinceLastReportRxDir uint32 + PacketsSeenSinceLastReportTxDir uint32 + PacketsSeenSinceLastReportRxDir uint32 + FlagsSeenSinceLastReportTxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } + FlagsSeenSinceLastReportRxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } TrafficDirection uint8 FlagsSeenTxDir uint8 FlagsSeenRxDir uint8 @@ -55,12 +81,27 @@ type packetparserPacket struct { Tsval uint32 Tsecr uint32 } - ObservationPoint uint8 - TrafficDirection uint8 - Proto uint8 - Flags uint8 - IsReply bool - _ [3]byte + ObservationPoint uint8 + TrafficDirection uint8 + Proto uint8 + _ [1]byte + Flags uint16 + IsReply bool + _ [1]byte + PreviouslyObservedPackets uint32 + PreviouslyObservedBytes uint32 + PreviouslyObservedFlags struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } + _ [4]byte ConntrackMetadata struct { BytesTxCount uint64 BytesRxCount uint64 diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.go b/pkg/plugin/packetparser/packetparser_bpfel_x86.go index 321f836b0e..ce86707cca 100644 --- a/pkg/plugin/packetparser/packetparser_bpfel_x86.go +++ b/pkg/plugin/packetparser/packetparser_bpfel_x86.go @@ -13,9 +13,35 @@ import ( ) type packetparserCtEntry struct { - EvictionTime uint32 - LastReportTxDir uint32 - LastReportRxDir uint32 + EvictionTime uint32 + LastReportTxDir uint32 + LastReportRxDir uint32 + BytesSeenSinceLastReportTxDir uint32 + BytesSeenSinceLastReportRxDir uint32 + PacketsSeenSinceLastReportTxDir uint32 + PacketsSeenSinceLastReportRxDir uint32 + FlagsSeenSinceLastReportTxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } + FlagsSeenSinceLastReportRxDir struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } TrafficDirection uint8 FlagsSeenTxDir uint8 FlagsSeenRxDir uint8 @@ -55,12 +81,27 @@ type packetparserPacket struct { Tsval uint32 Tsecr uint32 } - ObservationPoint uint8 - TrafficDirection uint8 - Proto uint8 - Flags uint8 - IsReply bool - _ [3]byte + ObservationPoint uint8 + TrafficDirection uint8 + Proto uint8 + _ [1]byte + Flags uint16 + IsReply bool + _ [1]byte + PreviouslyObservedPackets uint32 + PreviouslyObservedBytes uint32 + PreviouslyObservedFlags struct { + Syn uint32 + Ack uint32 + Fin uint32 + Rst uint32 + Psh uint32 + Urg uint32 + Ece uint32 + Cwr uint32 + Ns uint32 + } + _ [4]byte ConntrackMetadata struct { BytesTxCount uint64 BytesRxCount uint64 diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index c11ef9cef9..002e04a057 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -568,6 +568,8 @@ func (p *packetParser) processRecord(ctx context.Context, id int) { zap.Int("worker_id", id), ) + metrics.ParsedPacketsCounter.WithLabelValues().Inc() + var bpfEvent packetparserPacket err := binary.Read(bytes.NewReader(record.RawSample), binary.LittleEndian, &bpfEvent) if err != nil { @@ -607,6 +609,10 @@ func (p *packetParser) processRecord(ctx context.Context, id int) { // Add packet size to the flow's metadata. utils.AddPacketSize(meta, bpfEvent.Bytes) + // Add previously observed byte and packet counts to the flow's metadata + utils.AddPreviouslyObservedBytes(meta, bpfEvent.PreviouslyObservedBytes) + utils.AddPreviouslyObservedPackets(meta, bpfEvent.PreviouslyObservedPackets) + // Add the TCP metadata to the flow. tcpMetadata := bpfEvent.TcpMetadata utils.AddTCPFlags( @@ -617,6 +623,21 @@ func (p *packetParser) processRecord(ctx context.Context, id int) { uint16((bpfEvent.Flags&TCPFlagRST)>>2), // nolint:gomnd // 2 is the offset for RST. uint16((bpfEvent.Flags&TCPFlagPSH)>>3), // nolint:gomnd // 3 is the offset for PSH. uint16((bpfEvent.Flags&TCPFlagURG)>>5), // nolint:gomnd // 5 is the offset for URG. + uint16((bpfEvent.Flags&TCPFlagECE)>>6), // nolint:gomnd // 6 is the offset for ECE. + uint16((bpfEvent.Flags&TCPFlagCWR)>>7), // nolint:gomnd // 7 is the offset for CWR. + uint16((bpfEvent.Flags&TCPFlagNS)>>8), // nolint:gomnd // 8 is the offset for NS. + ) + utils.AddPreviouslyObservedTCPFlags( + meta, + bpfEvent.PreviouslyObservedFlags.Syn, + bpfEvent.PreviouslyObservedFlags.Ack, + bpfEvent.PreviouslyObservedFlags.Fin, + bpfEvent.PreviouslyObservedFlags.Rst, + bpfEvent.PreviouslyObservedFlags.Psh, + bpfEvent.PreviouslyObservedFlags.Urg, + bpfEvent.PreviouslyObservedFlags.Ece, + bpfEvent.PreviouslyObservedFlags.Cwr, + bpfEvent.PreviouslyObservedFlags.Ns, ) // For packets originating from node, we use tsval as the tcpID. diff --git a/pkg/plugin/packetparser/types_linux.go b/pkg/plugin/packetparser/types_linux.go index 4fc06f35c3..c220ba65af 100644 --- a/pkg/plugin/packetparser/types_linux.go +++ b/pkg/plugin/packetparser/types_linux.go @@ -28,6 +28,7 @@ const ( TCPFlagURG TCPFlagECE TCPFlagCWR + TCPFlagNS ) const ( diff --git a/pkg/plugin/tcpretrans/tcpretrans_linux.go b/pkg/plugin/tcpretrans/tcpretrans_linux.go index 9895dc78a9..1f4b994f4e 100644 --- a/pkg/plugin/tcpretrans/tcpretrans_linux.go +++ b/pkg/plugin/tcpretrans/tcpretrans_linux.go @@ -137,8 +137,8 @@ func (t *tcpretrans) eventHandler(event *types.Event) { t.l.Warn("Could not convert tracer Event to flow", zap.Any("tracer event", event)) return } - syn, ack, fin, rst, psh, urg := getTcpFlags(event.Tcpflags) - utils.AddTCPFlags(fl, syn, ack, fin, rst, psh, urg) + syn, ack, fin, rst, psh, urg, ece, cwr, ns := getTCPFlags(event.Tcpflags) + utils.AddTCPFlags(fl, syn, ack, fin, rst, psh, urg, ece, cwr, ns) // This is only for development purposes. // Removing this makes logs way too chatter-y. @@ -151,7 +151,8 @@ func (t *tcpretrans) eventHandler(event *types.Event) { }) } -func getTcpFlags(flags string) (syn, ack, fin, rst, psh, urg uint16) { +//nolint:gocritic // This should be rewritten to return a struct. +func getTCPFlags(flags string) (syn, ack, fin, rst, psh, urg, ece, cwr, ns uint16) { // this limiter is used in IG to put all the flags together syn, ack, fin, rst, psh, urg = 0, 0, 0, 0, 0, 0 result := strings.Split(flags, "|") @@ -169,6 +170,12 @@ func getTcpFlags(flags string) (syn, ack, fin, rst, psh, urg uint16) { psh = 1 case "URG": urg = 1 + case "ECE": + ece = 1 + case "CWR": + cwr = 1 + case "NS": + ns = 1 } } return diff --git a/pkg/utils/flow_utils.go b/pkg/utils/flow_utils.go index cffbeed2f9..1ad3b84c3b 100644 --- a/pkg/utils/flow_utils.go +++ b/pkg/utils/flow_utils.go @@ -133,7 +133,7 @@ func AddRetinaMetadata(f *flow.Flow, meta *RetinaMetadata) { f.Extensions = ext } -func AddTCPFlags(f *flow.Flow, syn, ack, fin, rst, psh, urg uint16) { +func AddTCPFlags(f *flow.Flow, syn, ack, fin, rst, psh, urg, ece, cwr, ns uint16) { if f.GetL4().GetTCP() == nil { return } @@ -145,9 +145,76 @@ func AddTCPFlags(f *flow.Flow, syn, ack, fin, rst, psh, urg uint16) { RST: rst == uint16(1), PSH: psh == uint16(1), URG: urg == uint16(1), + ECE: ece == uint16(1), + CWR: cwr == uint16(1), + NS: ns == uint16(1), } } +// AddPreviouslyObservedTCPFlags adds the previously observed TCP flags to the flows's metadata. +func AddPreviouslyObservedTCPFlags(meta *RetinaMetadata, syn, ack, fin, rst, psh, urg, ece, cwr, ns uint32) { + if meta == nil { + return + } + meta.PreviouslyObservedTcpFlags = map[string]uint32{ + SYN: syn, + ACK: ack, + FIN: fin, + RST: rst, + PSH: psh, + URG: urg, + ECE: ece, + CWR: cwr, + NS: ns, + } +} + +func PreviouslyObservedTCPFlags(f *flow.Flow) map[string]uint32 { + e := f.GetExtensions() + if e == nil { + return nil + } + k := &RetinaMetadata{} + e.UnmarshalTo(k) //nolint:errcheck // ignore errors + return k.GetPreviouslyObservedTcpFlags() +} + +// AddPreviouslyObservedBytes adds the previously observed bytes to the flow's metadata. +func AddPreviouslyObservedBytes(meta *RetinaMetadata, bytes uint32) { + if meta == nil { + return + } + meta.PreviouslyObservedBytes = bytes +} + +func PreviouslyObservedBytes(f *flow.Flow) uint32 { + e := f.GetExtensions() + if e == nil { + return 0 + } + k := &RetinaMetadata{} + e.UnmarshalTo(k) //nolint:errcheck // ignore errors + return k.GetPreviouslyObservedBytes() +} + +// AddPreviouslyObservedPackets adds the previously observed packets to the flow's metadata. +func AddPreviouslyObservedPackets(meta *RetinaMetadata, packets uint32) { + if meta == nil { + return + } + meta.PreviouslyObservedPackets = packets +} + +func PreviouslyObservedPackets(f *flow.Flow) uint32 { + e := f.GetExtensions() + if e == nil { + return 0 + } + k := &RetinaMetadata{} + e.UnmarshalTo(k) //nolint:errcheck // ignore errors + return k.GetPreviouslyObservedPackets() +} + func AddTCPFlagsBool(f *flow.Flow, syn, ack, fin, rst, psh, urg bool) { if f.GetL4().GetTCP() == nil { return diff --git a/pkg/utils/metadata_linux.pb.go b/pkg/utils/metadata_linux.pb.go index 7455a1191a..6914c0b3e3 100644 --- a/pkg/utils/metadata_linux.pb.go +++ b/pkg/utils/metadata_linux.pb.go @@ -144,6 +144,10 @@ type RetinaMetadata struct { TcpId uint64 `protobuf:"varint,4,opt,name=tcp_id,json=tcpId,proto3" json:"tcp_id,omitempty"` // Drop reason in Retina. DropReason DropReason `protobuf:"varint,5,opt,name=drop_reason,json=dropReason,proto3,enum=utils.DropReason" json:"drop_reason,omitempty"` + // Sampling metadata, for packetparser. + PreviouslyObservedPackets uint32 `protobuf:"varint,6,opt,name=previously_observed_packets,json=previouslyObservedPackets,proto3" json:"previously_observed_packets,omitempty"` + PreviouslyObservedBytes uint32 `protobuf:"varint,7,opt,name=previously_observed_bytes,json=previouslyObservedBytes,proto3" json:"previously_observed_bytes,omitempty"` + PreviouslyObservedTcpFlags map[string]uint32 `protobuf:"bytes,8,rep,name=previously_observed_tcp_flags,json=previouslyObservedTcpFlags,proto3" json:"previously_observed_tcp_flags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` } func (x *RetinaMetadata) Reset() { @@ -213,12 +217,33 @@ func (x *RetinaMetadata) GetDropReason() DropReason { return DropReason_IPTABLE_RULE_DROP } +func (x *RetinaMetadata) GetPreviouslyObservedPackets() uint32 { + if x != nil { + return x.PreviouslyObservedPackets + } + return 0 +} + +func (x *RetinaMetadata) GetPreviouslyObservedBytes() uint32 { + if x != nil { + return x.PreviouslyObservedBytes + } + return 0 +} + +func (x *RetinaMetadata) GetPreviouslyObservedTcpFlags() map[string]uint32 { + if x != nil { + return x.PreviouslyObservedTcpFlags + } + return nil +} + var File_pkg_utils_metadata_linux_proto protoreflect.FileDescriptor var file_pkg_utils_metadata_linux_proto_rawDesc = []byte{ 0x0a, 0x1e, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x05, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x74, 0x69, + 0x12, 0x05, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x22, 0x86, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, @@ -230,24 +255,44 @@ var file_pkg_utils_metadata_linux_proto_rawDesc = []byte{ 0x52, 0x05, 0x74, 0x63, 0x70, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, - 0x0a, 0x64, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2a, 0x2f, 0x0a, 0x07, 0x44, - 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x51, 0x55, 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x0c, - 0x0a, 0x08, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x02, 0x2a, 0xa5, 0x01, 0x0a, - 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x49, - 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, 0x44, 0x52, 0x4f, 0x50, - 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x4e, 0x41, - 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x43, 0x50, 0x5f, - 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x02, 0x12, - 0x14, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x5f, 0x42, 0x41, - 0x53, 0x49, 0x43, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x43, 0x50, 0x5f, 0x43, 0x4c, 0x4f, - 0x53, 0x45, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x4f, - 0x4e, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x4b, 0x5f, 0x41, 0x44, 0x44, 0x5f, 0x44, 0x52, 0x4f, 0x50, - 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x44, 0x52, - 0x4f, 0x50, 0x10, 0x06, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2f, 0x72, 0x65, 0x74, - 0x69, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x64, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x1b, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x19, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, + 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x78, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, + 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, + 0x63, 0x70, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, + 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, + 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, 0x67, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, + 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, 0x67, + 0x73, 0x1a, 0x4d, 0x0a, 0x1f, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x2a, 0x2f, 0x0a, 0x07, 0x44, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x51, 0x55, 0x45, 0x52, + 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, + 0x02, 0x2a, 0xa5, 0x01, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x12, 0x15, 0x0a, 0x11, 0x49, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, + 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x50, 0x54, 0x41, 0x42, + 0x4c, 0x45, 0x5f, 0x4e, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x15, 0x0a, + 0x11, 0x54, 0x43, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x42, 0x41, 0x53, + 0x49, 0x43, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x5f, 0x41, 0x43, 0x43, 0x45, + 0x50, 0x54, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x43, + 0x50, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x04, 0x12, + 0x16, 0x0a, 0x12, 0x43, 0x4f, 0x4e, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x4b, 0x5f, 0x41, 0x44, 0x44, + 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x06, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x2f, 0x72, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, + 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -263,20 +308,22 @@ func file_pkg_utils_metadata_linux_proto_rawDescGZIP() []byte { } var file_pkg_utils_metadata_linux_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_utils_metadata_linux_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pkg_utils_metadata_linux_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_pkg_utils_metadata_linux_proto_goTypes = []any{ (DNSType)(0), // 0: utils.DNSType (DropReason)(0), // 1: utils.DropReason (*RetinaMetadata)(nil), // 2: utils.RetinaMetadata + nil, // 3: utils.RetinaMetadata.PreviouslyObservedTcpFlagsEntry } var file_pkg_utils_metadata_linux_proto_depIdxs = []int32{ 0, // 0: utils.RetinaMetadata.dns_type:type_name -> utils.DNSType 1, // 1: utils.RetinaMetadata.drop_reason:type_name -> utils.DropReason - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 3, // 2: utils.RetinaMetadata.previously_observed_tcp_flags:type_name -> utils.RetinaMetadata.PreviouslyObservedTcpFlagsEntry + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_pkg_utils_metadata_linux_proto_init() } @@ -304,7 +351,7 @@ func file_pkg_utils_metadata_linux_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_utils_metadata_linux_proto_rawDesc, NumEnums: 2, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/utils/metadata_linux.proto b/pkg/utils/metadata_linux.proto index c0e13aa444..9e939bccd1 100644 --- a/pkg/utils/metadata_linux.proto +++ b/pkg/utils/metadata_linux.proto @@ -15,6 +15,11 @@ message RetinaMetadata { // Drop reason in Retina. DropReason drop_reason = 5; + + // Sampling metadata, for packetparser. + uint32 previously_observed_packets = 6; + uint32 previously_observed_bytes = 7; + map previously_observed_tcp_flags = 8; } enum DNSType { diff --git a/pkg/utils/metadata_windows.pb.go b/pkg/utils/metadata_windows.pb.go index 1347fb144a..c6b45e6dfb 100644 --- a/pkg/utils/metadata_windows.pb.go +++ b/pkg/utils/metadata_windows.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v3.19.1 -// source: metadata_windows.proto +// protoc v4.24.2 +// source: pkg/utils/metadata_windows.proto package utils @@ -53,11 +53,11 @@ func (x DNSType) String() string { } func (DNSType) Descriptor() protoreflect.EnumDescriptor { - return file_metadata_windows_proto_enumTypes[0].Descriptor() + return file_pkg_utils_metadata_windows_proto_enumTypes[0].Descriptor() } func (DNSType) Type() protoreflect.EnumType { - return &file_metadata_windows_proto_enumTypes[0] + return &file_pkg_utils_metadata_windows_proto_enumTypes[0] } func (x DNSType) Number() protoreflect.EnumNumber { @@ -66,7 +66,7 @@ func (x DNSType) Number() protoreflect.EnumNumber { // Deprecated: Use DNSType.Descriptor instead. func (DNSType) EnumDescriptor() ([]byte, []int) { - return file_metadata_windows_proto_rawDescGZIP(), []int{0} + return file_pkg_utils_metadata_windows_proto_rawDescGZIP(), []int{0} } type DropReason int32 @@ -1316,11 +1316,11 @@ func (x DropReason) String() string { } func (DropReason) Descriptor() protoreflect.EnumDescriptor { - return file_metadata_windows_proto_enumTypes[1].Descriptor() + return file_pkg_utils_metadata_windows_proto_enumTypes[1].Descriptor() } func (DropReason) Type() protoreflect.EnumType { - return &file_metadata_windows_proto_enumTypes[1] + return &file_pkg_utils_metadata_windows_proto_enumTypes[1] } func (x DropReason) Number() protoreflect.EnumNumber { @@ -1329,7 +1329,7 @@ func (x DropReason) Number() protoreflect.EnumNumber { // Deprecated: Use DropReason.Descriptor instead. func (DropReason) EnumDescriptor() ([]byte, []int) { - return file_metadata_windows_proto_rawDescGZIP(), []int{1} + return file_pkg_utils_metadata_windows_proto_rawDescGZIP(), []int{1} } type RetinaMetadata struct { @@ -1345,12 +1345,16 @@ type RetinaMetadata struct { TcpId uint64 `protobuf:"varint,4,opt,name=tcp_id,json=tcpId,proto3" json:"tcp_id,omitempty"` // Drop reason in Retina. DropReason DropReason `protobuf:"varint,5,opt,name=drop_reason,json=dropReason,proto3,enum=utils.DropReason" json:"drop_reason,omitempty"` + // Sampling metadata, for packetparser. + PreviouslyObservedPackets uint32 `protobuf:"varint,6,opt,name=previously_observed_packets,json=previouslyObservedPackets,proto3" json:"previously_observed_packets,omitempty"` + PreviouslyObservedBytes uint32 `protobuf:"varint,7,opt,name=previously_observed_bytes,json=previouslyObservedBytes,proto3" json:"previously_observed_bytes,omitempty"` + PreviouslyObservedTcpFlags map[string]uint32 `protobuf:"bytes,8,rep,name=previously_observed_tcp_flags,json=previouslyObservedTcpFlags,proto3" json:"previously_observed_tcp_flags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` } func (x *RetinaMetadata) Reset() { *x = RetinaMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_metadata_windows_proto_msgTypes[0] + mi := &file_pkg_utils_metadata_windows_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1363,7 +1367,7 @@ func (x *RetinaMetadata) String() string { func (*RetinaMetadata) ProtoMessage() {} func (x *RetinaMetadata) ProtoReflect() protoreflect.Message { - mi := &file_metadata_windows_proto_msgTypes[0] + mi := &file_pkg_utils_metadata_windows_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1376,7 +1380,7 @@ func (x *RetinaMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use RetinaMetadata.ProtoReflect.Descriptor instead. func (*RetinaMetadata) Descriptor() ([]byte, []int) { - return file_metadata_windows_proto_rawDescGZIP(), []int{0} + return file_pkg_utils_metadata_windows_proto_rawDescGZIP(), []int{0} } func (x *RetinaMetadata) GetBytes() uint32 { @@ -1414,914 +1418,958 @@ func (x *RetinaMetadata) GetDropReason() DropReason { return DropReason_Drop_Unknown } -var File_metadata_windows_proto protoreflect.FileDescriptor +func (x *RetinaMetadata) GetPreviouslyObservedPackets() uint32 { + if x != nil { + return x.PreviouslyObservedPackets + } + return 0 +} + +func (x *RetinaMetadata) GetPreviouslyObservedBytes() uint32 { + if x != nil { + return x.PreviouslyObservedBytes + } + return 0 +} -var file_metadata_windows_proto_rawDesc = []byte{ - 0x0a, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x22, - 0xc1, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x75, 0x74, 0x69, - 0x6c, 0x73, 0x2e, 0x44, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x74, 0x63, 0x70, 0x5f, - 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x63, 0x70, 0x49, 0x64, 0x12, - 0x32, 0x0a, 0x0b, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x44, 0x72, 0x6f, - 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x2a, 0x2f, 0x0a, 0x07, 0x44, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, - 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x51, - 0x55, 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, - 0x53, 0x45, 0x10, 0x02, 0x2a, 0xe0, 0x69, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, - 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x61, 0x74, 0x61, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, - 0x74, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, - 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x6f, 0x74, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x65, 0x64, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x42, 0x75, 0x73, 0x79, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x10, 0x08, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x56, 0x4c, 0x41, 0x4e, 0x10, 0x09, - 0x12, 0x19, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x65, 0x64, 0x56, 0x4c, 0x41, 0x4e, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, - 0x4d, 0x41, 0x43, 0x10, 0x0b, 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x10, 0x0c, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x50, 0x76, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x10, - 0x0d, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x51, 0x6f, 0x73, 0x10, 0x0e, 0x12, - 0x0e, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x10, 0x0f, 0x12, - 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4d, 0x61, 0x63, 0x53, 0x70, 0x6f, 0x6f, 0x66, - 0x69, 0x6e, 0x67, 0x10, 0x10, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x68, - 0x63, 0x70, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0x11, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0x12, 0x12, - 0x17, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x10, 0x13, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, - 0x10, 0x14, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x52, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x73, 0x73, - 0x69, 0x6e, 0x67, 0x10, 0x15, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x16, 0x12, 0x14, 0x0a, - 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4d, 0x54, 0x55, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x10, 0x17, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x46, 0x77, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x10, 0x18, 0x12, 0x1a, 0x0a, - 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x56, 0x6c, 0x61, - 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x10, 0x19, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x65, 0x73, 0x74, 0x4d, 0x61, 0x63, - 0x10, 0x1a, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x63, 0x10, 0x1b, 0x12, 0x1f, 0x0a, - 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x4e, 0x42, 0x54, 0x6f, 0x6f, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x10, 0x1c, 0x12, 0x0c, - 0x0a, 0x08, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x57, 0x6e, 0x76, 0x10, 0x1d, 0x12, 0x13, 0x0a, 0x0f, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x74, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, - 0x1e, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x49, 0x63, 0x6d, 0x70, 0x10, 0x1f, 0x12, 0x24, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x10, 0x20, 0x12, 0x14, - 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x69, 0x63, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x10, 0x21, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x10, - 0x22, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, - 0x44, 0x61, 0x74, 0x61, 0x46, 0x6c, 0x6f, 0x77, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x10, 0x23, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x74, 0x61, - 0x67, 0x67, 0x65, 0x64, 0x10, 0x24, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, - 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x44, 0x51, 0x75, 0x65, 0x75, 0x65, 0x10, 0x25, 0x12, - 0x11, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4c, 0x6f, 0x77, 0x50, 0x6f, 0x77, 0x65, 0x72, - 0x10, 0x26, 0x12, 0x0f, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x50, 0x61, 0x75, 0x73, 0x65, - 0x10, 0xc9, 0x01, 0x12, 0x0f, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x52, 0x65, 0x73, 0x65, - 0x74, 0x10, 0xca, 0x01, 0x12, 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x65, 0x6e, - 0x64, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x10, 0xcb, 0x01, 0x12, 0x1a, 0x0a, 0x15, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4e, 0x6f, 0x74, 0x42, - 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xcc, 0x01, 0x12, 0x11, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xcd, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x10, 0xce, 0x01, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x6f, 0x73, 0x74, - 0x4f, 0x75, 0x74, 0x4f, 0x66, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x10, 0xcf, 0x01, 0x12, 0x16, - 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x6f, 0x4c, - 0x6f, 0x6e, 0x67, 0x10, 0xd0, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, - 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x6f, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x10, 0xd1, 0x01, 0x12, - 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xd2, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x43, 0x72, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xd3, 0x01, 0x12, - 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x61, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x10, 0xd4, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x63, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xd5, 0x01, 0x12, - 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x10, 0xd6, 0x01, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, - 0x65, 0x61, 0x64, 0x51, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x10, 0xd7, 0x01, 0x12, 0x18, - 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x44, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x10, 0xd8, 0x01, 0x12, 0x11, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x52, 0x78, 0x51, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0xd9, 0x01, 0x12, 0x18, 0x0a, 0x13, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x10, 0xda, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x6d, - 0x61, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xdb, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, - 0xdc, 0x01, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x65, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xdd, 0x01, 0x12, 0x16, - 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x10, 0xde, 0x01, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x43, - 0x6f, 0x61, 0x6c, 0x65, 0x73, 0x63, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xdf, - 0x01, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, 0x6c, 0x61, 0x6e, 0x53, 0x70, - 0x6f, 0x6f, 0x66, 0x69, 0x6e, 0x67, 0x10, 0xe1, 0x01, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x55, 0x6e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x45, 0x74, 0x68, 0x65, 0x72, - 0x54, 0x79, 0x70, 0x65, 0x10, 0xe2, 0x01, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x56, 0x70, 0x6f, 0x72, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x10, 0xe3, 0x01, 0x12, 0x1a, 0x0a, 0x15, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x74, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x69, 0x73, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x10, 0xe4, 0x01, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, - 0x91, 0x03, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, 0x66, 0x4e, 0x6f, 0x74, - 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0x92, 0x03, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, - 0x64, 0x79, 0x10, 0x93, 0x03, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, 0x4d, - 0x42, 0x75, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x94, 0x03, 0x12, 0x1b, 0x0a, 0x16, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x50, - 0x61, 0x63, 0x6b, 0x65, 0x74, 0x10, 0xd9, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x6e, 0x61, 0x70, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xda, 0x04, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x45, 0x74, 0x68, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdb, 0x04, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xdc, 0x04, 0x12, 0x20, 0x0a, 0x1b, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x6f, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, 0x10, 0xdd, 0x04, 0x12, 0x23, - 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x10, 0xde, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, - 0x10, 0xdf, 0x04, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, - 0xe0, 0x04, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4c, 0x73, 0x6f, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xe1, 0x04, 0x12, - 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x55, 0x73, 0x6f, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xe2, 0x04, 0x12, 0x1a, 0x0a, 0x15, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, - 0x65, 0x64, 0x69, 0x75, 0x6d, 0x10, 0xe3, 0x04, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x72, 0x70, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x10, 0xe4, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x46, 0x4c, 0x5f, 0x4e, 0x6f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x10, 0xe5, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x46, 0x4c, 0x5f, 0x54, 0x6f, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x4e, 0x65, 0x74, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x73, 0x10, 0xe6, 0x04, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x46, 0x4c, 0x5f, 0x46, 0x6c, 0x73, 0x4e, 0x70, 0x69, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, - 0x72, 0x6f, 0x70, 0x10, 0xe7, 0x04, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x41, - 0x72, 0x70, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xbd, 0x05, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x41, 0x72, 0x70, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x10, 0xbe, 0x05, - 0x12, 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x68, 0x63, 0x70, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x65, 0x72, 0x10, 0xbf, 0x05, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x10, 0xc0, - 0x05, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, - 0x6f, 0x6e, 0x49, 0x70, 0x10, 0xc1, 0x05, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x41, 0x72, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x10, 0xc2, 0x05, 0x12, 0x13, 0x0a, 0x0e, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x76, 0x34, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xc3, - 0x05, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x76, 0x36, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x10, 0xc4, 0x05, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4d, - 0x61, 0x63, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xc5, 0x05, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4e, 0x6f, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0xc6, 0x05, 0x12, 0x1e, 0x0a, - 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x69, 0x63, 0x61, 0x73, 0x74, 0x4e, 0x6f, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xc7, 0x05, 0x12, 0x1d, 0x0a, - 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x69, 0x63, 0x61, 0x73, 0x74, 0x50, 0x6f, 0x72, - 0x74, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0xc8, 0x05, 0x12, 0x1e, 0x0a, 0x19, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x62, - 0x61, 0x63, 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xc9, 0x05, 0x12, 0x17, 0x0a, 0x12, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x76, 0x36, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x65, 0x72, 0x10, 0xca, 0x05, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x10, 0xcb, 0x05, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x10, 0xcc, 0x05, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x44, 0x50, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xcd, 0x05, 0x12, 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x50, 0x6f, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x10, 0xce, 0x05, 0x12, - 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x69, 0x63, 0x53, 0x75, 0x73, 0x70, 0x65, - 0x6e, 0x64, 0x65, 0x64, 0x10, 0xcf, 0x05, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x10, 0x85, 0x07, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x4e, 0x6f, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x65, 0x64, 0x10, 0x86, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x55, 0x6e, 0x72, 0x65, 0x61, - 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x87, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x50, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, - 0x61, 0x62, 0x6c, 0x65, 0x10, 0x88, 0x07, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0x89, 0x07, 0x12, - 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4d, 0x61, 0x6c, 0x66, 0x6f, - 0x72, 0x6d, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x8a, 0x07, 0x12, 0x14, 0x0a, - 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x10, 0x8b, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x42, - 0x65, 0x79, 0x6f, 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x10, 0x8c, 0x07, 0x12, 0x1b, 0x0a, - 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x8d, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x54, 0x6f, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x44, 0x65, 0x63, - 0x61, 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x8e, 0x07, 0x12, 0x27, - 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x68, 0x69, 0x62, - 0x69, 0x74, 0x65, 0x64, 0x10, 0x8f, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x10, 0x90, - 0x07, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x10, 0x91, 0x07, 0x12, 0x1d, - 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x48, 0x6f, 0x70, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x92, 0x07, 0x12, 0x1f, 0x0a, - 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x55, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x93, 0x07, 0x12, 0x16, - 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x73, 0x63, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x10, 0x94, 0x07, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x78, - 0x10, 0x95, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, - 0x72, 0x62, 0x69, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x68, 0x61, 0x6e, 0x64, - 0x6c, 0x65, 0x64, 0x10, 0x96, 0x07, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x62, 0x73, 0x6f, - 0x72, 0x62, 0x10, 0x97, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x44, 0x6f, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x74, 0x75, - 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x98, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x99, 0x07, 0x12, 0x25, - 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x10, 0x9a, 0x07, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9b, 0x07, 0x12, 0x19, 0x0a, 0x14, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9c, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9d, 0x07, 0x12, 0x1d, 0x0a, - 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x9e, 0x07, 0x12, 0x1f, 0x0a, 0x1a, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x10, 0x9f, 0x07, 0x12, 0x1b, 0x0a, - 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa0, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x6e, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x79, 0x44, - 0x61, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa1, 0x07, 0x12, 0x1b, 0x0a, - 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x61, 0x77, 0x44, 0x61, 0x74, 0x61, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa2, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa3, 0x07, 0x12, 0x2a, 0x0a, 0x25, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x75, 0x74, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x65, 0x64, 0x10, 0xa4, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x4e, 0x65, 0x78, 0x74, - 0x48, 0x6f, 0x70, 0x10, 0xa5, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xa6, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xa7, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x53, 0x75, 0x62, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xa8, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0xa9, - 0x07, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, - 0x6e, 0x70, 0x69, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xaa, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x45, 0x74, 0x68, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xab, 0x07, 0x12, 0x25, 0x0a, - 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x55, - 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x10, 0xac, 0x07, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xad, - 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, - 0x6e, 0x70, 0x69, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4c, 0x73, 0x6f, 0x49, 0x6e, 0x66, - 0x6f, 0x10, 0xae, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x73, 0x6f, - 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xaf, 0x07, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x10, 0xb0, 0x07, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x10, 0xb1, 0x07, 0x12, 0x16, 0x0a, 0x11, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x10, 0xb2, 0x07, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x10, 0xb3, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x10, 0xb4, 0x07, - 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x51, 0x75, 0x65, 0x75, - 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0xb5, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0xb6, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x10, - 0xb7, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, - 0x6d, 0x70, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x10, 0xb8, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x73, 0x75, 0x6d, 0x10, 0xb9, 0x07, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x10, 0xba, 0x07, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, - 0x63, 0x6d, 0x70, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x10, 0xbb, 0x07, 0x12, - 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x55, - 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbc, 0x07, 0x12, 0x22, 0x0a, - 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x54, 0x72, 0x75, - 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x49, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xbd, - 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, - 0x70, 0x4f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x7a, 0x65, 0x64, 0x49, 0x70, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x10, 0xbe, 0x07, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x10, 0xbf, - 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x10, 0xc0, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x10, 0xc1, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xc2, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x50, 0x61, 0x74, 0x68, 0x52, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xc3, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x10, 0xc4, 0x07, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x49, 0x63, 0x6d, 0x70, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xc5, 0x07, 0x12, 0x1f, - 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x42, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x54, 0x6f, 0x6f, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x10, 0xc6, 0x07, 0x12, - 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x41, - 0x6e, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x10, 0xc7, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x48, 0x6f, 0x70, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xc8, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, - 0x6f, 0x64, 0x65, 0x10, 0xc9, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x4c, - 0x69, 0x6e, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xca, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x54, 0x72, 0x75, 0x6e, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x4e, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xcb, 0x07, 0x12, - 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, - 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x10, 0xcc, 0x07, 0x12, 0x20, 0x0a, 0x1b, +func (x *RetinaMetadata) GetPreviouslyObservedTcpFlags() map[string]uint32 { + if x != nil { + return x.PreviouslyObservedTcpFlags + } + return nil +} + +var File_pkg_utils_metadata_windows_proto protoreflect.FileDescriptor + +var file_pkg_utils_metadata_windows_proto_rawDesc = []byte{ + 0x0a, 0x20, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x05, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x22, 0x86, 0x04, 0x0a, 0x0e, 0x52, 0x65, + 0x74, 0x69, 0x6e, 0x61, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x44, 0x4e, 0x53, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, + 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x74, 0x63, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x05, 0x74, 0x63, 0x70, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x72, 0x6f, + 0x70, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, + 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x52, 0x0a, 0x64, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, + 0x1b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x19, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x3a, 0x0a, + 0x19, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x78, 0x0a, 0x1d, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, + 0x5f, 0x74, 0x63, 0x70, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x35, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, + 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, + 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, + 0x73, 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, + 0x61, 0x67, 0x73, 0x1a, 0x4d, 0x0a, 0x1f, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, + 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x2a, 0x2f, 0x0a, 0x07, 0x44, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, + 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x51, 0x55, + 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, + 0x45, 0x10, 0x02, 0x2a, 0xe0, 0x69, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x44, 0x61, 0x74, 0x61, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x05, + 0x12, 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x6f, 0x74, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x65, 0x64, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, + 0x75, 0x73, 0x79, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x10, 0x08, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x56, 0x4c, 0x41, 0x4e, 0x10, 0x09, 0x12, + 0x19, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x56, 0x4c, 0x41, 0x4e, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4d, + 0x41, 0x43, 0x10, 0x0b, 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x10, 0x0c, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x50, 0x76, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x10, 0x0d, + 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x51, 0x6f, 0x73, 0x10, 0x0e, 0x12, 0x0e, + 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x10, 0x0f, 0x12, 0x14, + 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4d, 0x61, 0x63, 0x53, 0x70, 0x6f, 0x6f, 0x66, 0x69, + 0x6e, 0x67, 0x10, 0x10, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x68, 0x63, + 0x70, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0x11, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0x12, 0x12, 0x17, + 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x10, 0x13, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x10, + 0x14, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x10, 0x15, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x16, 0x12, 0x14, 0x0a, 0x10, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4d, 0x54, 0x55, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x10, 0x17, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x61, 0x74, 0x69, 0x76, + 0x65, 0x46, 0x77, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x10, 0x18, 0x12, 0x1a, 0x0a, 0x16, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x56, 0x6c, 0x61, 0x6e, + 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x10, 0x19, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x65, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x10, + 0x1a, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x63, 0x10, 0x1b, 0x12, 0x1f, 0x0a, 0x1b, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x69, 0x72, 0x73, + 0x74, 0x4e, 0x42, 0x54, 0x6f, 0x6f, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x10, 0x1c, 0x12, 0x0c, 0x0a, + 0x08, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x57, 0x6e, 0x76, 0x10, 0x1d, 0x12, 0x13, 0x0a, 0x0f, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x74, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0x1e, + 0x12, 0x15, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x49, 0x63, 0x6d, 0x70, 0x10, 0x1f, 0x12, 0x24, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x10, 0x20, 0x12, 0x14, 0x0a, + 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x69, 0x63, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x10, 0x21, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x10, 0x22, + 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x44, + 0x61, 0x74, 0x61, 0x46, 0x6c, 0x6f, 0x77, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, + 0x23, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x65, 0x64, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x74, 0x61, 0x67, + 0x67, 0x65, 0x64, 0x10, 0x24, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x44, 0x51, 0x75, 0x65, 0x75, 0x65, 0x10, 0x25, 0x12, 0x11, + 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4c, 0x6f, 0x77, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x10, + 0x26, 0x12, 0x0f, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x50, 0x61, 0x75, 0x73, 0x65, 0x10, + 0xc9, 0x01, 0x12, 0x0f, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74, + 0x10, 0xca, 0x01, 0x12, 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x65, 0x6e, 0x64, + 0x41, 0x62, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x10, 0xcb, 0x01, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4e, 0x6f, 0x74, 0x42, 0x6f, + 0x75, 0x6e, 0x64, 0x10, 0xcc, 0x01, 0x12, 0x11, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xcd, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, + 0xce, 0x01, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x6f, 0x73, 0x74, 0x4f, + 0x75, 0x74, 0x4f, 0x66, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x10, 0xcf, 0x01, 0x12, 0x16, 0x0a, + 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x6f, 0x4c, 0x6f, + 0x6e, 0x67, 0x10, 0xd0, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x72, + 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x6f, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x10, 0xd1, 0x01, 0x12, 0x1a, + 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xd2, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x43, 0x72, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xd3, 0x01, 0x12, 0x1a, + 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x61, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x10, 0xd4, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x46, 0x63, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xd5, 0x01, 0x12, 0x15, + 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x10, 0xd6, 0x01, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x65, + 0x61, 0x64, 0x51, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x10, 0xd7, 0x01, 0x12, 0x18, 0x0a, + 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x73, + 0x63, 0x61, 0x72, 0x64, 0x10, 0xd8, 0x01, 0x12, 0x11, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x52, 0x78, 0x51, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0xd9, 0x01, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x10, 0xda, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x6d, 0x61, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xdb, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xdc, + 0x01, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xdd, 0x01, 0x12, 0x16, 0x0a, + 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x10, 0xde, 0x01, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x43, 0x6f, + 0x61, 0x6c, 0x65, 0x73, 0x63, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xdf, 0x01, + 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, 0x6c, 0x61, 0x6e, 0x53, 0x70, 0x6f, + 0x6f, 0x66, 0x69, 0x6e, 0x67, 0x10, 0xe1, 0x01, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x55, 0x6e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x45, 0x74, 0x68, 0x65, 0x72, 0x54, + 0x79, 0x70, 0x65, 0x10, 0xe2, 0x01, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, + 0x70, 0x6f, 0x72, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x10, 0xe3, 0x01, 0x12, 0x1a, 0x0a, 0x15, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x74, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x69, 0x73, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x10, 0xe4, 0x01, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x91, + 0x03, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, 0x66, 0x4e, 0x6f, 0x74, 0x52, + 0x65, 0x61, 0x64, 0x79, 0x10, 0x92, 0x03, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, + 0x79, 0x10, 0x93, 0x03, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x56, 0x4d, 0x42, + 0x75, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x94, 0x03, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x10, 0xd9, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x6e, 0x61, 0x70, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x10, 0xda, 0x04, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdb, 0x04, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, + 0x65, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xdc, 0x04, 0x12, 0x20, 0x0a, 0x1b, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x74, + 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, 0x10, 0xdd, 0x04, 0x12, 0x23, 0x0a, + 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, + 0xde, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, + 0xdf, 0x04, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0xe0, + 0x04, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x4c, 0x73, 0x6f, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xe1, 0x04, 0x12, 0x1b, + 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x55, 0x73, 0x6f, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xe2, 0x04, 0x12, 0x1a, 0x0a, 0x15, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, + 0x64, 0x69, 0x75, 0x6d, 0x10, 0xe3, 0x04, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x46, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x72, 0x70, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x10, 0xe4, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, + 0x4c, 0x5f, 0x4e, 0x6f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x10, 0xe5, 0x04, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, + 0x4c, 0x5f, 0x54, 0x6f, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x4e, 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, + 0x65, 0x72, 0x73, 0x10, 0xe6, 0x04, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x46, + 0x4c, 0x5f, 0x46, 0x6c, 0x73, 0x4e, 0x70, 0x69, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x72, + 0x6f, 0x70, 0x10, 0xe7, 0x04, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x41, 0x72, + 0x70, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xbd, 0x05, 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x41, 0x72, 0x70, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x10, 0xbe, 0x05, 0x12, + 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x44, 0x68, 0x63, 0x70, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x65, 0x72, 0x10, 0xbf, 0x05, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x10, 0xc0, 0x05, + 0x12, 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, + 0x6e, 0x49, 0x70, 0x10, 0xc1, 0x05, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x41, + 0x72, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x10, 0xc2, 0x05, 0x12, 0x13, 0x0a, 0x0e, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x76, 0x34, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xc3, 0x05, + 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x76, 0x36, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x10, 0xc4, 0x05, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4d, 0x61, + 0x63, 0x47, 0x75, 0x61, 0x72, 0x64, 0x10, 0xc5, 0x05, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4e, 0x6f, 0x44, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0xc6, 0x05, 0x12, 0x1e, 0x0a, 0x19, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x69, 0x63, 0x61, 0x73, 0x74, 0x4e, 0x6f, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xc7, 0x05, 0x12, 0x1d, 0x0a, 0x18, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x55, 0x6e, 0x69, 0x63, 0x61, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, + 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0xc8, 0x05, 0x12, 0x1e, 0x0a, 0x19, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, + 0x63, 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xc9, 0x05, 0x12, 0x17, 0x0a, 0x12, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x76, 0x36, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, + 0x72, 0x10, 0xca, 0x05, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x10, 0xcb, 0x05, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x10, 0xcc, 0x05, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x44, 0x50, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x10, 0xcd, 0x05, 0x12, 0x15, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x50, 0x6f, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x10, 0xce, 0x05, 0x12, 0x16, + 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x69, 0x63, 0x53, 0x75, 0x73, 0x70, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x10, 0xcf, 0x05, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x10, 0x85, 0x07, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x4e, 0x6f, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x65, 0x64, 0x10, 0x86, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x63, + 0x68, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x87, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x4e, 0x4c, 0x5f, 0x50, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, + 0x62, 0x6c, 0x65, 0x10, 0x88, 0x07, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0x89, 0x07, 0x12, 0x1c, + 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4d, 0x61, 0x6c, 0x66, 0x6f, 0x72, + 0x6d, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x8a, 0x07, 0x12, 0x14, 0x0a, 0x0f, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, + 0x8b, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x42, 0x65, + 0x79, 0x6f, 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x10, 0x8c, 0x07, 0x12, 0x1b, 0x0a, 0x16, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x8d, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x54, 0x6f, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x44, 0x65, 0x63, 0x61, + 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x8e, 0x07, 0x12, 0x27, 0x0a, + 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x50, 0x72, 0x6f, 0x68, 0x69, 0x62, 0x69, + 0x74, 0x65, 0x64, 0x10, 0x8f, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x10, 0x90, 0x07, + 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x10, 0x91, 0x07, 0x12, 0x1d, 0x0a, + 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x48, 0x6f, 0x70, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x92, 0x07, 0x12, 0x1f, 0x0a, 0x1a, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, + 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x93, 0x07, 0x12, 0x16, 0x0a, + 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x73, 0x63, 0x50, 0x61, 0x63, 0x6b, + 0x65, 0x74, 0x10, 0x94, 0x07, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x10, + 0x95, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, + 0x62, 0x69, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x68, 0x61, 0x6e, 0x64, 0x6c, + 0x65, 0x64, 0x10, 0x96, 0x07, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x62, 0x73, 0x6f, 0x72, + 0x62, 0x10, 0x97, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x44, 0x6f, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x74, 0x75, 0x45, + 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x98, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x99, 0x07, 0x12, 0x25, 0x0a, + 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x10, 0x9a, 0x07, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9b, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x10, 0x9c, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9d, 0x07, 0x12, 0x1d, 0x0a, 0x18, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x9e, 0x07, 0x12, 0x1f, 0x0a, 0x1a, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x10, 0x9f, 0x07, 0x12, 0x1b, 0x0a, 0x16, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa0, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x6e, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x79, 0x44, 0x61, + 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa1, 0x07, 0x12, 0x1b, 0x0a, 0x16, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x52, 0x61, 0x77, 0x44, 0x61, 0x74, 0x61, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa2, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa3, 0x07, 0x12, 0x2a, 0x0a, 0x25, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x75, 0x74, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x65, 0x64, 0x10, 0xa4, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x4e, 0x65, 0x78, 0x74, 0x48, + 0x6f, 0x70, 0x10, 0xa5, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xa6, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x10, 0xa7, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x53, 0x75, 0x62, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xa8, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0xa9, 0x07, + 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, + 0x70, 0x69, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x10, 0xaa, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x4e, 0x6f, 0x45, 0x74, 0x68, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xab, 0x07, 0x12, 0x25, 0x0a, 0x20, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, 0x55, 0x6e, + 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x10, 0xac, 0x07, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, + 0x70, 0x73, 0x6e, 0x70, 0x69, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xad, 0x07, + 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, + 0x70, 0x69, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4c, 0x73, 0x6f, 0x49, 0x6e, 0x66, 0x6f, + 0x10, 0xae, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, + 0x70, 0x73, 0x6e, 0x70, 0x69, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x73, 0x6f, 0x49, + 0x6e, 0x66, 0x6f, 0x10, 0xaf, 0x07, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, + 0xb0, 0x07, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x10, 0xb1, 0x07, 0x12, 0x16, 0x0a, 0x11, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x42, 0x61, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x10, 0xb2, 0x07, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4c, + 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x10, 0xb3, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x10, 0xb4, 0x07, 0x12, + 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x51, 0x75, 0x65, 0x75, 0x65, + 0x46, 0x75, 0x6c, 0x6c, 0x10, 0xb5, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x10, 0xb6, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x10, 0xb7, + 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, + 0x70, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x10, 0xb8, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, + 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x10, 0xb9, 0x07, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, + 0xba, 0x07, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, + 0x6d, 0x70, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x10, 0xbb, 0x07, 0x12, 0x1c, + 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x55, 0x6e, + 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbc, 0x07, 0x12, 0x22, 0x0a, 0x1d, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x54, 0x72, 0x75, 0x6e, + 0x63, 0x61, 0x74, 0x65, 0x64, 0x49, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xbd, 0x07, + 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, + 0x4f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x7a, 0x65, 0x64, 0x49, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x10, 0xbe, 0x07, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x10, 0xbf, 0x07, + 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x10, 0xc0, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x10, 0xc1, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xc2, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x50, 0x61, 0x74, 0x68, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xc3, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x10, 0xc4, 0x07, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, + 0x63, 0x6d, 0x70, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xc5, 0x07, 0x12, 0x1f, 0x0a, + 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x42, 0x75, 0x66, + 0x66, 0x65, 0x72, 0x54, 0x6f, 0x6f, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x10, 0xc6, 0x07, 0x12, 0x23, + 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x41, 0x6e, + 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x10, 0xc7, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, + 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x48, 0x6f, 0x70, 0x4c, + 0x69, 0x6d, 0x69, 0x74, 0x10, 0xc8, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, + 0x64, 0x65, 0x10, 0xc9, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x4c, 0x69, + 0x6e, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xca, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x4e, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xcb, 0x07, 0x12, 0x2b, + 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x10, 0xcc, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x4d, 0x74, 0x75, 0x10, 0xcd, 0x07, 0x12, 0x2e, 0x0a, + 0x29, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x49, + 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xce, 0x07, 0x12, 0x2d, 0x0a, + 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xcf, 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x4d, 0x74, 0x75, 0x10, 0xcd, 0x07, 0x12, 0x2e, - 0x0a, 0x29, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xce, 0x07, 0x12, 0x2d, - 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xcf, 0x07, 0x12, 0x22, 0x0a, - 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x52, 0x64, 0x6e, 0x73, 0x73, 0x10, 0xd0, - 0x07, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, - 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x44, 0x6e, 0x73, - 0x73, 0x6c, 0x10, 0xd1, 0x07, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x72, 0x73, 0x69, - 0x6e, 0x67, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xd2, 0x07, 0x12, 0x1b, 0x0a, 0x16, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xd3, 0x07, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, + 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x52, 0x64, 0x6e, 0x73, 0x73, 0x10, 0xd0, 0x07, + 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, + 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x4f, 0x70, 0x74, 0x44, 0x6e, 0x73, 0x73, + 0x6c, 0x10, 0xd1, 0x07, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x49, 0x63, 0x6d, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6e, + 0x67, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xd2, 0x07, 0x12, 0x1b, 0x0a, 0x16, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xd3, 0x07, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x41, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x10, 0xd4, 0x07, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, + 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x44, + 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0xd5, 0x07, 0x12, + 0x33, 0x0a, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, + 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x10, 0xd6, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x10, 0xd7, 0x07, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x73, + 0x74, 0x41, 0x6e, 0x64, 0x53, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x65, 0x64, 0x10, 0xd8, 0x07, + 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, + 0x4e, 0x64, 0x4c, 0x69, 0x6e, 0x6b, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x49, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xd9, 0x07, 0x12, 0x25, 0x0a, 0x20, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x44, 0x75, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x10, 0xda, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, + 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x74, 0x41, 0x50, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x10, 0xdb, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x41, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x10, 0xd4, 0x07, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, - 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x72, 0x6f, 0x6d, - 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0xd5, 0x07, - 0x12, 0x33, 0x0a, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, - 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x72, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x10, 0xd6, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4e, 0x64, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x10, 0xd7, 0x07, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, - 0x73, 0x74, 0x41, 0x6e, 0x64, 0x53, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x65, 0x64, 0x10, 0xd8, - 0x07, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, - 0x70, 0x4e, 0x64, 0x4c, 0x69, 0x6e, 0x6b, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x49, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xd9, 0x07, 0x12, 0x25, 0x0a, - 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x44, 0x75, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x10, 0xda, 0x07, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, - 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x74, 0x41, 0x50, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x10, 0xdb, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x4d, 0x6c, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x10, 0xdc, 0x07, 0x12, 0x21, 0x0a, 0x1c, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x4d, 0x6c, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x10, 0xdd, 0x07, 0x12, - 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x64, 0x4d, 0x6c, 0x64, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x10, 0xde, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x74, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x64, 0x10, 0xdf, 0x07, 0x12, 0x1d, - 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x49, 0x6e, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x10, 0xe0, 0x07, 0x12, 0x1d, 0x0a, + 0x4d, 0x6c, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x10, 0xdc, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x4d, 0x6c, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x10, 0xdd, 0x07, 0x12, 0x28, + 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x64, 0x4d, 0x6c, 0x64, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x10, 0xde, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x4e, 0x6f, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x6c, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x64, 0x10, 0xdf, 0x07, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x49, 0x6e, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x10, 0xe1, 0x07, 0x12, 0x1f, 0x0a, 0x1a, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x44, 0x6c, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xe2, 0x07, 0x12, 0x22, 0x0a, - 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x4e, 0x6f, 0x74, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x64, 0x10, 0xe3, - 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4e, 0x6c, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x10, 0xe4, 0x07, 0x12, - 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, - 0x69, 0x55, 0x72, 0x6f, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x45, - 0x78, 0x63, 0x65, 0x65, 0x64, 0x73, 0x4d, 0x74, 0x75, 0x10, 0xe5, 0x07, 0x12, 0x21, 0x0a, 0x1c, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x46, 0x72, 0x61, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x10, 0xe6, 0x07, 0x12, - 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x10, 0xe7, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, - 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x10, 0xe8, 0x07, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, - 0x63, 0x6d, 0x70, 0x4a, 0x75, 0x6d, 0x62, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x10, 0xe9, 0x07, 0x12, - 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x53, 0x77, 0x55, 0x73, 0x6f, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xea, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x6e, - 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0xb0, 0x09, 0x12, 0x23, 0x0a, 0x1e, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x73, 0x74, 0x10, 0xb1, - 0x09, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0xb2, 0x09, 0x12, - 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0xb3, 0x09, 0x12, - 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xb4, 0x09, - 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x74, 0x68, 0x10, 0xb5, 0x09, 0x12, 0x1b, - 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x10, 0xb6, 0x09, 0x12, 0x20, 0x0a, 0x1b, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xb7, 0x09, 0x12, 0x19, 0x0a, - 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x41, 0x63, 0x6b, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0xb8, 0x09, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x79, - 0x6e, 0x10, 0xb9, 0x09, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, - 0x54, 0x5f, 0x52, 0x73, 0x74, 0x10, 0xba, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x79, 0x6e, 0x52, 0x63, 0x76, 0x64, 0x53, 0x79, 0x6e, - 0x10, 0xbb, 0x09, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, - 0x5f, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x74, 0x61, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x10, 0xbc, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x50, 0x61, 0x77, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, - 0xbd, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, - 0x4c, 0x61, 0x6e, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xbe, 0x09, 0x12, 0x1a, 0x0a, - 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4d, 0x69, 0x73, 0x73, 0x65, - 0x64, 0x52, 0x65, 0x73, 0x65, 0x74, 0x10, 0xbf, 0x09, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x57, 0x69, - 0x6e, 0x64, 0x6f, 0x77, 0x10, 0xc0, 0x09, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xc1, 0x09, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x10, 0xc2, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, - 0x45, 0x54, 0x5f, 0x54, 0x63, 0x62, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x10, 0xc3, 0x09, - 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x46, 0x69, - 0x6e, 0x57, 0x61, 0x69, 0x74, 0x32, 0x10, 0xc4, 0x09, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x52, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x10, 0xc5, 0x09, 0x12, 0x1a, 0x0a, 0x15, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x46, 0x69, 0x6e, 0x52, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x64, 0x10, 0xc6, 0x09, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0xc7, 0x09, 0x12, 0x1f, 0x0a, - 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, 0x63, 0x62, 0x4e, 0x6f, - 0x74, 0x49, 0x6e, 0x54, 0x63, 0x62, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x10, 0xc8, 0x09, 0x12, 0x32, - 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, 0x69, 0x6d, 0x65, - 0x57, 0x61, 0x69, 0x74, 0x54, 0x63, 0x62, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x52, - 0x73, 0x74, 0x4f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x10, - 0xc9, 0x09, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, - 0x54, 0x69, 0x6d, 0x65, 0x57, 0x61, 0x69, 0x74, 0x54, 0x63, 0x62, 0x53, 0x79, 0x6e, 0x41, 0x6e, - 0x64, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0xca, 0x09, 0x12, 0x1a, - 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, 0x69, 0x6d, 0x65, - 0x57, 0x61, 0x69, 0x74, 0x54, 0x63, 0x62, 0x10, 0xcb, 0x09, 0x12, 0x2e, 0x0a, 0x29, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x79, 0x6e, 0x41, 0x63, 0x6b, 0x57, 0x69, - 0x74, 0x68, 0x46, 0x61, 0x73, 0x74, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xcc, 0x09, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x50, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x10, 0xcd, 0x09, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, - 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x79, 0x6e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xce, 0x09, - 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x41, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xcf, - 0x09, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x10, 0xd0, 0x09, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, - 0x75, 0x78, 0x5f, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6e, 0x67, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, - 0x65, 0x10, 0x95, 0x0a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, - 0x4d, 0x75, 0x78, 0x5f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x4d, 0x69, 0x73, 0x73, 0x10, 0x96, 0x0a, 0x12, 0x32, 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x49, 0x43, 0x4d, 0x50, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x97, 0x0a, 0x12, 0x2e, 0x0a, 0x29, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x49, 0x43, 0x4d, 0x50, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x4e, 0x6f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x98, 0x0a, 0x12, 0x34, 0x0a, 0x2f, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x45, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x61, 0x69, 0x72, 0x70, 0x69, 0x6e, 0x4e, 0x65, 0x78, 0x74, 0x68, - 0x6f, 0x70, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, - 0x99, 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, - 0x78, 0x5f, 0x4e, 0x6f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x10, 0x9a, 0x0a, 0x12, 0x28, 0x0a, 0x23, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x65, 0x78, 0x74, - 0x68, 0x6f, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x10, 0x9b, 0x0a, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, - 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x43, 0x6c, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9c, 0x0a, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9d, 0x0a, 0x12, 0x21, 0x0a, 0x1c, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x48, 0x6f, 0x70, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x9e, 0x0a, 0x12, - 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x50, - 0x61, 0x63, 0x6b, 0x65, 0x74, 0x42, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x68, 0x61, 0x6e, 0x4d, - 0x54, 0x55, 0x10, 0x9f, 0x0a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, - 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, - 0x65, 0x10, 0xa0, 0x0a, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, - 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0xa1, 0x0a, 0x12, 0x27, - 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x10, 0xa2, 0x0a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x4e, 0x6f, - 0x74, 0x4f, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xa3, 0x0a, 0x12, 0x38, 0x0a, 0x33, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, - 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x4d, 0x69, 0x73, 0x73, 0x4e, 0x41, 0x54, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x10, 0xa4, 0x0a, 0x12, 0x2f, 0x0a, 0x2a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, - 0x75, 0x78, 0x5f, 0x4e, 0x41, 0x54, 0x49, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x43, 0x61, 0x6e, 0x74, - 0x42, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, - 0x70, 0x10, 0xa5, 0x0a, 0x12, 0x36, 0x0a, 0x31, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, - 0x4d, 0x75, 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x49, 0x6e, 0x49, 0x74, 0x73, 0x41, 0x72, 0x72, 0x69, 0x76, 0x61, 0x6c, 0x43, 0x6f, - 0x6d, 0x70, 0x61, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xa6, 0x0a, 0x12, 0x34, 0x0a, 0x2f, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, - 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x4e, 0x6f, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x10, - 0xa7, 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, - 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x73, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x65, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x10, 0xa8, 0x0a, 0x12, 0x3a, 0x0a, 0x35, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, - 0x65, 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x50, 0x61, - 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x4e, 0x6f, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x54, 0x6f, 0x4e, 0x41, 0x54, 0x10, 0xa9, 0x0a, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4d, 0x75, 0x78, 0x52, 0x65, 0x6a, 0x65, 0x63, - 0x74, 0x10, 0xaa, 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, - 0x4d, 0x75, 0x78, 0x5f, 0x44, 0x69, 0x70, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x10, 0xab, 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4d, 0x75, 0x78, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x73, - 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xac, - 0x0a, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, - 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x69, 0x61, 0x67, 0x50, 0x61, 0x63, 0x6b, - 0x65, 0x74, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x10, 0xad, 0x0a, 0x12, 0x25, - 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x44, 0x69, - 0x61, 0x67, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x73, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x10, 0xae, 0x0a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, - 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x48, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0xaf, 0x0a, 0x12, 0x16, - 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x42, 0x61, 0x64, - 0x53, 0x70, 0x69, 0x10, 0xf9, 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, - 0x70, 0x73, 0x65, 0x63, 0x5f, 0x53, 0x41, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x10, 0xfa, 0x0a, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x53, 0x41, 0x10, - 0xfb, 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, - 0x5f, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x46, 0x61, 0x69, 0x6c, - 0x65, 0x64, 0x10, 0xfc, 0x0a, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, - 0x73, 0x65, 0x63, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, - 0x74, 0x10, 0xfd, 0x0a, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, - 0x65, 0x63, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xfe, 0x0a, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x65, - 0x78, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x10, 0xff, 0x0a, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x41, 0x75, 0x74, 0x68, 0x46, 0x69, 0x72, 0x65, - 0x77, 0x61, 0x6c, 0x6c, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x80, 0x0b, 0x12, 0x1c, 0x0a, 0x17, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, - 0x6c, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x81, 0x0b, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x10, 0x82, 0x0b, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, - 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x64, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x73, 0x74, 0x10, 0x83, 0x0b, 0x12, 0x22, 0x0a, - 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, - 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x84, - 0x0b, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, - 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, - 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x85, 0x0b, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x4d, 0x61, 0x78, - 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x10, 0x86, 0x0b, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x4b, 0x65, - 0x79, 0x6d, 0x6f, 0x64, 0x4e, 0x6f, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x87, - 0x0b, 0x12, 0x2c, 0x0a, 0x27, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, - 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x72, 0x49, 0x70, 0x52, 0x61, 0x74, - 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x65, 0x75, 0x65, 0x73, 0x10, 0x88, 0x0b, 0x12, - 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x4e, 0x6f, - 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x10, 0x89, 0x0b, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x55, 0x6e, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x66, 0x75, 0x6c, 0x10, 0x8a, 0x0b, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x4e, 0x65, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4c, - 0x61, 0x79, 0x6f, 0x75, 0x74, 0x50, 0x61, 0x72, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, - 0x65, 0x10, 0xdd, 0x0b, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, - 0x43, 0x78, 0x5f, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x73, 0x75, 0x6d, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xde, 0x0b, 0x12, 0x1c, 0x0a, - 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x4e, 0x69, 0x63, 0x51, - 0x75, 0x65, 0x75, 0x65, 0x53, 0x74, 0x6f, 0x70, 0x10, 0xdf, 0x0b, 0x12, 0x26, 0x0a, 0x21, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x4e, 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x10, 0xe0, 0x0b, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, - 0x78, 0x5f, 0x4c, 0x53, 0x4f, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xe1, 0x0b, 0x12, - 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x55, 0x53, - 0x4f, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xe2, 0x0b, 0x12, 0x32, 0x0a, 0x2d, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x42, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x41, 0x6e, 0x64, - 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x10, 0xe3, 0x0b, 0x12, - 0x14, 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x42, 0x65, 0x67, - 0x69, 0x6e, 0x10, 0xb8, 0x17, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, - 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x42, 0x65, 0x67, 0x69, 0x6e, - 0x10, 0xb9, 0x17, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xba, 0x17, 0x12, 0x1a, 0x0a, 0x15, 0x44, + 0x6c, 0x69, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x10, 0xe0, 0x07, 0x12, 0x1d, 0x0a, 0x18, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x10, 0xe1, 0x07, 0x12, 0x1f, 0x0a, 0x1a, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x44, 0x6c, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x49, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xe2, 0x07, 0x12, 0x22, 0x0a, 0x1d, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x41, 0x72, 0x70, 0x4e, 0x6f, 0x74, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x64, 0x10, 0xe3, 0x07, + 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x4e, 0x6c, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x10, 0xe4, 0x07, 0x12, 0x2b, + 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x70, 0x73, 0x6e, 0x70, 0x69, + 0x55, 0x72, 0x6f, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x45, 0x78, + 0x63, 0x65, 0x65, 0x64, 0x73, 0x4d, 0x74, 0x75, 0x10, 0xe5, 0x07, 0x12, 0x21, 0x0a, 0x1c, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, 0x6d, 0x70, 0x46, 0x72, 0x61, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x10, 0xe6, 0x07, 0x12, 0x24, + 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, + 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x10, 0xe7, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, + 0xe8, 0x07, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x49, 0x63, + 0x6d, 0x70, 0x4a, 0x75, 0x6d, 0x62, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x10, 0xe9, 0x07, 0x12, 0x19, + 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x4c, 0x5f, 0x53, 0x77, 0x55, 0x73, 0x6f, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xea, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x6e, 0x73, + 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0xb0, 0x09, 0x12, 0x23, 0x0a, 0x1e, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x73, 0x74, 0x10, 0xb1, 0x09, + 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0xb2, 0x09, 0x12, 0x1e, + 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x73, 0x75, 0x6d, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0xb3, 0x09, 0x12, 0x1f, + 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xb4, 0x09, 0x12, + 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x74, 0x68, 0x10, 0xb5, 0x09, 0x12, 0x1b, 0x0a, + 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x10, 0xb6, 0x09, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x49, + 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xb7, 0x09, 0x12, 0x19, 0x0a, 0x14, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x41, 0x63, 0x6b, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x10, 0xb8, 0x09, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x79, 0x6e, + 0x10, 0xb9, 0x09, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, + 0x5f, 0x52, 0x73, 0x74, 0x10, 0xba, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x79, 0x6e, 0x52, 0x63, 0x76, 0x64, 0x53, 0x79, 0x6e, 0x10, + 0xbb, 0x09, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, + 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x74, 0x61, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x10, 0xbc, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, + 0x4e, 0x45, 0x54, 0x5f, 0x50, 0x61, 0x77, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xbd, + 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4c, + 0x61, 0x6e, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xbe, 0x09, 0x12, 0x1a, 0x0a, 0x15, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x10, 0xbf, 0x09, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x57, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x10, 0xc0, 0x09, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, + 0x4e, 0x45, 0x54, 0x5f, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xc1, 0x09, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x10, 0xc2, 0x09, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, + 0x54, 0x5f, 0x54, 0x63, 0x62, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x10, 0xc3, 0x09, 0x12, + 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x46, 0x69, 0x6e, + 0x57, 0x61, 0x69, 0x74, 0x32, 0x10, 0xc4, 0x09, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x52, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x79, + 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x10, 0xc5, 0x09, 0x12, 0x1a, 0x0a, 0x15, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x46, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x64, 0x10, 0xc6, 0x09, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0xc7, 0x09, 0x12, 0x1f, 0x0a, 0x1a, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, 0x63, 0x62, 0x4e, 0x6f, 0x74, + 0x49, 0x6e, 0x54, 0x63, 0x62, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x10, 0xc8, 0x09, 0x12, 0x32, 0x0a, + 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, 0x69, 0x6d, 0x65, 0x57, + 0x61, 0x69, 0x74, 0x54, 0x63, 0x62, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x52, 0x73, + 0x74, 0x4f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x10, 0xc9, + 0x09, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, + 0x69, 0x6d, 0x65, 0x57, 0x61, 0x69, 0x74, 0x54, 0x63, 0x62, 0x53, 0x79, 0x6e, 0x41, 0x6e, 0x64, + 0x4f, 0x74, 0x68, 0x65, 0x72, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0xca, 0x09, 0x12, 0x1a, 0x0a, + 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x54, 0x69, 0x6d, 0x65, 0x57, + 0x61, 0x69, 0x74, 0x54, 0x63, 0x62, 0x10, 0xcb, 0x09, 0x12, 0x2e, 0x0a, 0x29, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x53, 0x79, 0x6e, 0x41, 0x63, 0x6b, 0x57, 0x69, 0x74, + 0x68, 0x46, 0x61, 0x73, 0x74, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xcc, 0x09, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x50, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x10, 0xcd, 0x09, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, + 0x45, 0x54, 0x5f, 0x53, 0x79, 0x6e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xce, 0x09, 0x12, + 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x41, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xcf, 0x09, + 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x4e, 0x45, 0x54, 0x5f, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, + 0xd0, 0x09, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, + 0x78, 0x5f, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6e, 0x67, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, + 0x10, 0x95, 0x0a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, + 0x75, 0x78, 0x5f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x4d, 0x69, 0x73, 0x73, 0x10, 0x96, 0x0a, 0x12, 0x32, 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x49, 0x43, 0x4d, 0x50, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x97, 0x0a, 0x12, 0x2e, 0x0a, 0x29, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x49, 0x43, 0x4d, 0x50, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4e, + 0x6f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x98, 0x0a, 0x12, 0x34, 0x0a, 0x2f, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x48, 0x61, 0x69, 0x72, 0x70, 0x69, 0x6e, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, + 0x70, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x99, + 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, + 0x5f, 0x4e, 0x6f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x10, 0x9a, 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x65, 0x78, 0x74, 0x68, + 0x6f, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, + 0x72, 0x65, 0x10, 0x9b, 0x0a, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, + 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x43, 0x6c, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x10, 0x9c, 0x0a, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, + 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x9d, 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x48, 0x6f, 0x70, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x10, 0x9e, 0x0a, 0x12, 0x24, + 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x42, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x68, 0x61, 0x6e, 0x4d, 0x54, + 0x55, 0x10, 0x9f, 0x0a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, + 0x4d, 0x75, 0x78, 0x5f, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, + 0x10, 0xa0, 0x0a, 0x12, 0x18, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, + 0x75, 0x78, 0x5f, 0x4e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0xa1, 0x0a, 0x12, 0x27, 0x0a, + 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x10, 0xa2, 0x0a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, + 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x4e, 0x6f, 0x74, + 0x4f, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xa3, 0x0a, 0x12, 0x38, 0x0a, 0x33, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x45, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x4d, 0x69, 0x73, 0x73, 0x4e, 0x41, 0x54, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x10, + 0xa4, 0x0a, 0x12, 0x2f, 0x0a, 0x2a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, + 0x78, 0x5f, 0x4e, 0x41, 0x54, 0x49, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x43, 0x61, 0x6e, 0x74, 0x42, + 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, + 0x10, 0xa5, 0x0a, 0x12, 0x36, 0x0a, 0x31, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, + 0x75, 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x49, 0x6e, 0x49, 0x74, 0x73, 0x41, 0x72, 0x72, 0x69, 0x76, 0x61, 0x6c, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xa6, 0x0a, 0x12, 0x34, 0x0a, 0x2f, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x4e, 0x6f, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x10, 0xa7, + 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, + 0x5f, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x73, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x65, + 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x10, 0xa8, 0x0a, 0x12, 0x3a, 0x0a, 0x35, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x50, 0x61, 0x6e, + 0x64, 0x50, 0x6f, 0x72, 0x74, 0x4e, 0x6f, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, + 0x6f, 0x4e, 0x41, 0x54, 0x10, 0xa9, 0x0a, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4d, 0x75, 0x78, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, + 0x10, 0xaa, 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, + 0x75, 0x78, 0x5f, 0x44, 0x69, 0x70, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x10, 0xab, 0x0a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, + 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x4d, 0x75, 0x78, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xac, 0x0a, + 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, + 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x69, 0x61, 0x67, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x10, 0xad, 0x0a, 0x12, 0x25, 0x0a, + 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, 0x4d, 0x75, 0x78, 0x5f, 0x44, 0x69, 0x61, + 0x67, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x73, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x10, 0xae, 0x0a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x53, 0x6c, 0x62, + 0x4d, 0x75, 0x78, 0x5f, 0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x48, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0xaf, 0x0a, 0x12, 0x16, 0x0a, + 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x42, 0x61, 0x64, 0x53, + 0x70, 0x69, 0x10, 0xf9, 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, + 0x73, 0x65, 0x63, 0x5f, 0x53, 0x41, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x64, 0x10, 0xfa, 0x0a, 0x12, 0x17, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x53, 0x41, 0x10, 0xfb, + 0x0a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, + 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x10, 0xfc, 0x0a, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, + 0x65, 0x63, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x10, 0xfd, 0x0a, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, + 0x63, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0xfe, 0x0a, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x65, 0x78, + 0x74, 0x44, 0x72, 0x6f, 0x70, 0x10, 0xff, 0x0a, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x41, 0x75, 0x74, 0x68, 0x46, 0x69, 0x72, 0x65, 0x77, + 0x61, 0x6c, 0x6c, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x80, 0x0b, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, + 0x65, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x81, 0x0b, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x10, 0x82, 0x0b, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, + 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x73, 0x74, 0x10, 0x83, 0x0b, 0x12, 0x22, 0x0a, 0x1d, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, + 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x84, 0x0b, + 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, + 0x6f, 0x73, 0x70, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x85, 0x0b, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x4d, 0x61, 0x78, 0x45, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x10, 0x86, 0x0b, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, 0x6f, 0x73, 0x70, 0x5f, 0x4b, 0x65, 0x79, + 0x6d, 0x6f, 0x64, 0x4e, 0x6f, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x87, 0x0b, + 0x12, 0x2c, 0x0a, 0x27, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x44, + 0x6f, 0x73, 0x70, 0x5f, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x72, 0x49, 0x70, 0x52, 0x61, 0x74, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x65, 0x75, 0x65, 0x73, 0x10, 0x88, 0x0b, 0x12, 0x18, + 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x4e, 0x6f, 0x4d, + 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x10, 0x89, 0x0b, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x49, 0x70, 0x73, 0x65, 0x63, 0x5f, 0x55, 0x6e, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x66, 0x75, 0x6c, 0x10, 0x8a, 0x0b, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, + 0x65, 0x74, 0x43, 0x78, 0x5f, 0x4e, 0x65, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x61, + 0x79, 0x6f, 0x75, 0x74, 0x50, 0x61, 0x72, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, + 0x10, 0xdd, 0x0b, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, + 0x78, 0x5f, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xde, 0x0b, 0x12, 0x1c, 0x0a, 0x17, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x4e, 0x69, 0x63, 0x51, 0x75, + 0x65, 0x75, 0x65, 0x53, 0x74, 0x6f, 0x70, 0x10, 0xdf, 0x0b, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x4e, 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, + 0xe0, 0x0b, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, + 0x5f, 0x4c, 0x53, 0x4f, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xe1, 0x0b, 0x12, 0x1a, + 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x55, 0x53, 0x4f, + 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xe2, 0x0b, 0x12, 0x32, 0x0a, 0x2d, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x4e, 0x65, 0x74, 0x43, 0x78, 0x5f, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x42, + 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x41, 0x6e, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x10, 0xe3, 0x0b, 0x12, 0x14, + 0x0a, 0x0f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x42, 0x65, 0x67, 0x69, + 0x6e, 0x10, 0xb8, 0x17, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, + 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x10, + 0xb9, 0x17, 0x12, 0x16, 0x0a, 0x11, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xba, 0x17, 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x56, + 0x65, 0x72, 0x62, 0x10, 0xbb, 0x17, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x55, 0x72, 0x6c, 0x10, 0xbc, + 0x17, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xbd, 0x17, 0x12, + 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xbe, 0x17, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x56, 0x65, 0x72, 0x62, 0x10, 0xbb, 0x17, 0x12, 0x19, 0x0a, 0x14, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x55, 0x72, 0x6c, 0x10, - 0xbc, 0x17, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xbd, 0x17, - 0x12, 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xbe, 0x17, 0x12, 0x19, 0x0a, 0x14, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x4e, 0x75, 0x6d, 0x10, 0xbf, 0x17, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc0, 0x17, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc1, 0x17, 0x12, - 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, - 0x10, 0xc2, 0x17, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x6e, 0x55, 0x72, 0x6c, 0x10, 0xc3, 0x17, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4e, 0x6f, 0x74, 0x46, - 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xc4, 0x17, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc5, 0x17, 0x12, 0x28, 0x0a, 0x23, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x10, 0xc6, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, - 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x54, 0x6f, 0x6f, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x10, 0xc7, 0x17, 0x12, 0x1f, 0x0a, 0x1a, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x55, 0x72, 0x6c, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc8, 0x17, 0x12, 0x29, 0x0a, - 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x53, 0x61, 0x74, 0x69, 0x73, 0x66, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x10, 0xc9, 0x17, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x69, 0x73, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, - 0xca, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x10, 0xcb, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4e, 0x6f, 0x74, - 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x10, 0xcc, 0x17, 0x12, 0x21, - 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x10, 0xcd, - 0x17, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, - 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xce, 0x17, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, - 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x61, 0x70, - 0x69, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x10, 0xcf, 0x17, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x51, - 0x75, 0x65, 0x75, 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0xd0, 0x17, 0x12, 0x25, 0x0a, 0x20, 0x44, + 0x4e, 0x75, 0x6d, 0x10, 0xbf, 0x17, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc0, 0x17, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc1, 0x17, 0x12, 0x22, + 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x10, + 0xc2, 0x17, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, 0x64, 0x65, 0x6e, + 0x55, 0x72, 0x6c, 0x10, 0xc3, 0x17, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4e, 0x6f, 0x74, 0x46, 0x6f, + 0x75, 0x6e, 0x64, 0x10, 0xc4, 0x17, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc5, 0x17, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x10, - 0xd1, 0x17, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, - 0x79, 0x41, 0x70, 0x70, 0x10, 0xd2, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4a, 0x6f, 0x62, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x72, 0x65, 0x64, 0x10, 0xd3, 0x17, 0x12, 0x21, 0x0a, + 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x10, 0xc6, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, + 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x54, 0x6f, 0x6f, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x10, 0xc7, 0x17, 0x12, 0x1f, 0x0a, 0x1a, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x55, 0x72, 0x6c, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xc8, 0x17, 0x12, 0x29, 0x0a, 0x24, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x53, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x10, 0xc9, 0x17, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x69, 0x73, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xca, + 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x10, 0xcb, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4e, 0x6f, 0x74, 0x49, + 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x10, 0xcc, 0x17, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x41, 0x70, 0x70, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x75, 0x73, 0x79, 0x10, 0xd4, 0x17, - 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0xd5, 0x17, 0x12, - 0x1a, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x45, 0x6e, 0x64, 0x10, 0xd6, 0x17, 0x12, 0x1e, 0x0a, 0x19, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x10, 0xc8, 0x1a, 0x12, 0x22, 0x0a, 0x1d, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x10, 0xc9, 0x1a, 0x12, - 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, - 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x10, 0xca, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x10, 0xcb, 0x1a, - 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, - 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4e, 0x6f, - 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xcc, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, + 0x6f, 0x72, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x10, 0xcd, 0x17, + 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, + 0x69, 0x6d, 0x69, 0x74, 0x10, 0xce, 0x17, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x61, 0x70, 0x69, + 0x64, 0x46, 0x61, 0x69, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, + 0xcf, 0x17, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x51, 0x75, + 0x65, 0x75, 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0xd0, 0x17, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x10, 0xd1, + 0x17, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, 0x79, + 0x41, 0x70, 0x70, 0x10, 0xd2, 0x17, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4a, 0x6f, 0x62, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x72, 0x65, 0x64, 0x10, 0xd3, 0x17, 0x12, 0x21, 0x0a, 0x1c, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x41, 0x70, 0x70, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x75, 0x73, 0x79, 0x10, 0xd4, 0x17, 0x12, + 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0xd5, 0x17, 0x12, 0x1a, + 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x6c, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x5f, 0x45, 0x6e, 0x64, 0x10, 0xd6, 0x17, 0x12, 0x1e, 0x0a, 0x19, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, + 0x6c, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x10, 0xc8, 0x1a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, + 0x6c, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x10, 0xc9, 0x1a, 0x12, 0x23, + 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, + 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x10, 0xca, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x10, 0xcb, 0x1a, 0x12, + 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, + 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4e, 0x6f, 0x74, + 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xcc, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x10, 0xcd, + 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, + 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xce, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, + 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61, 0x41, 0x66, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x10, 0xcf, + 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x6f, 0x74, + 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xd0, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, + 0x48, 0x61, 0x6c, 0x66, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, + 0xd1, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x41, 0x75, 0x74, 0x68, 0x10, 0xd2, 0x1a, 0x12, 0x24, 0x0a, + 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, + 0x46, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x33, + 0x10, 0xd3, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x43, 0x65, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x10, 0xd4, 0x1a, 0x12, + 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, + 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x10, 0xd5, 0x1a, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, - 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x10, - 0xcd, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, - 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xce, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61, 0x41, 0x66, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x10, - 0xcf, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x6f, - 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xd0, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, + 0x74, 0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x53, 0x65, 0x6e, 0x64, 0x10, 0xd6, 0x1a, 0x12, + 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, + 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x75, 0x73, 0x68, 0x55, 0x70, 0x70, 0x65, 0x72, + 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x10, 0xd7, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, - 0x74, 0x48, 0x61, 0x6c, 0x66, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x10, 0xd1, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x41, 0x75, 0x74, 0x68, 0x10, 0xd2, 0x1a, 0x12, 0x24, - 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, - 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x33, 0x10, 0xd3, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x10, 0xd4, 0x1a, - 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, - 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, - 0x6d, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x10, 0xd5, 0x1a, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, - 0x6c, 0x74, 0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x53, 0x65, 0x6e, 0x64, 0x10, 0xd6, 0x1a, - 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, - 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x75, 0x73, 0x68, 0x55, 0x70, 0x70, 0x65, - 0x72, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x10, 0xd7, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, + 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x55, 0x70, 0x70, 0x65, 0x72, 0x41, 0x74, 0x74, 0x61, + 0x63, 0x68, 0x10, 0xd8, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, + 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0xd9, + 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xda, 0x1a, 0x12, 0x27, 0x0a, + 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, + 0x46, 0x61, 0x75, 0x6c, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, + 0x61, 0x69, 0x6c, 0x10, 0xdb, 0x1a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x72, + 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x10, 0xdc, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, - 0x6c, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x55, 0x70, 0x70, 0x65, 0x72, 0x41, 0x74, 0x74, - 0x61, 0x63, 0x68, 0x10, 0xd8, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, - 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, - 0xd9, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0xda, 0x1a, 0x12, 0x27, - 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, - 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x54, 0x61, 0x69, 0x6c, 0x10, 0xdb, 0x1a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x54, - 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x10, 0xdc, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x6f, 0x6c, 0x64, 0x10, - 0xdd, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, 0x10, 0xde, 0x1a, 0x12, 0x2d, 0x0a, 0x28, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xdf, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, + 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x6f, 0x6c, 0x64, 0x10, 0xdd, + 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, 0x10, 0xde, 0x1a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, - 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x65, - 0x64, 0x10, 0xe0, 0x1a, 0x12, 0x2e, 0x0a, 0x29, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x10, 0xe1, 0x1a, 0x12, 0x31, 0x0a, 0x2c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x6f, - 0x64, 0x69, 0x6e, 0x67, 0x10, 0xe2, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x10, 0xe3, 0x1a, 0x12, 0x27, - 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, - 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x10, 0xe4, 0x1a, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, - 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0xe5, 0x1a, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, + 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x10, 0xdf, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, - 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x10, 0xe6, 0x1a, 0x12, 0x24, - 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, - 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x10, 0xe7, 0x1a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x68, 0x75, 0x6e, - 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x10, 0xe8, 0x1a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, + 0x10, 0xe0, 0x1a, 0x12, 0x2e, 0x0a, 0x29, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x10, 0xe1, 0x1a, 0x12, 0x31, 0x0a, 0x2c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x10, 0xe2, 0x1a, 0x12, 0x25, 0x0a, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x10, 0xe3, 0x1a, 0x12, 0x27, 0x0a, + 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, + 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x10, 0xe4, 0x1a, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0xe5, 0x1a, 0x12, 0x23, 0x0a, 0x1e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x54, 0x72, 0x61, 0x69, - 0x6c, 0x65, 0x72, 0x73, 0x10, 0xe9, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x10, 0xe6, 0x1a, 0x12, 0x24, 0x0a, + 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, + 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x10, 0xe7, 0x1a, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, + 0x53, 0x74, 0x6f, 0x70, 0x10, 0xe8, 0x1a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x10, 0xea, - 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, - 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x45, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x73, - 0x54, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x10, 0xeb, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, - 0x6c, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, - 0x6e, 0x67, 0x10, 0xec, 0x1a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, - 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x75, 0x6c, - 0x74, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x64, - 0x69, 0x6e, 0x67, 0x73, 0x10, 0xed, 0x1a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x54, 0x72, 0x61, 0x69, 0x6c, + 0x65, 0x72, 0x73, 0x10, 0xe9, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x10, 0xea, 0x1a, + 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, + 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x45, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x54, + 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x10, 0xeb, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, + 0x67, 0x10, 0xec, 0x1a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, + 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x69, + 0x6e, 0x67, 0x73, 0x10, 0xed, 0x1a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, + 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x75, + 0x73, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x10, 0xee, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, + 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x64, + 0x10, 0xef, 0x1a, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x61, 0x6c, 0x66, 0x6f, + 0x72, 0x6d, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xf0, 0x1a, 0x12, 0x2e, 0x0a, 0x29, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, + 0x75, 0x6c, 0x74, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x4f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x10, 0xf1, 0x1a, 0x12, 0x2a, 0x0a, 0x25, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, + 0x75, 0x6c, 0x74, 0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x10, 0xf2, 0x1a, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, 0x5f, + 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, + 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x10, 0xf3, 0x1a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, + 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x6e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x10, 0xf4, 0x1a, 0x12, 0x2c, 0x0a, 0x27, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x10, 0xf5, + 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, + 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, + 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x79, 0x10, 0xf6, 0x1a, 0x12, 0x25, 0x0a, 0x20, + 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, + 0x61, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x10, 0xf7, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xf8, 0x1a, 0x12, 0x27, + 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, + 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x64, 0x10, 0xf9, 0x1a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, - 0x75, 0x73, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x10, 0xee, 0x1a, 0x12, 0x28, 0x0a, 0x23, 0x44, 0x72, + 0x75, 0x73, 0x68, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xfa, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, - 0x6c, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, - 0x64, 0x10, 0xef, 0x1a, 0x12, 0x26, 0x0a, 0x21, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x61, 0x6c, 0x66, - 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xf0, 0x1a, 0x12, 0x2e, 0x0a, 0x29, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, - 0x61, 0x75, 0x6c, 0x74, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x10, 0xf1, 0x1a, 0x12, 0x2a, 0x0a, 0x25, + 0x6c, 0x74, 0x47, 0x6f, 0x61, 0x77, 0x61, 0x79, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, + 0x10, 0xfb, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x62, 0x6f, 0x72, 0x74, + 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x41, 0x70, 0x70, 0x10, 0xfc, 0x1a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, - 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x10, 0xf2, 0x1a, 0x12, 0x2b, 0x0a, 0x26, 0x44, 0x72, 0x6f, 0x70, + 0x61, 0x75, 0x6c, 0x74, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xfd, 0x1a, 0x12, 0x2e, + 0x0a, 0x29, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, + 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x55, 0x70, + 0x67, 0x72, 0x61, 0x64, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xfe, 0x1a, 0x12, 0x32, + 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, + 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, + 0xff, 0x1a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x10, 0x80, 0x1b, 0x12, 0x32, 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, + 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x81, 0x1b, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, - 0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x10, 0xf3, 0x1a, 0x12, 0x2d, 0x0a, 0x28, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, - 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, - 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x10, 0xf4, 0x1a, 0x12, 0x2c, 0x0a, 0x27, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x10, - 0xf5, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, - 0x52, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x79, 0x10, 0xf6, 0x1a, 0x12, 0x25, 0x0a, - 0x20, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, - 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x10, 0xf7, 0x1a, 0x12, 0x29, 0x0a, 0x24, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x65, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xf8, 0x1a, 0x12, - 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, - 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x73, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xf9, 0x1a, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, + 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x82, 0x1b, 0x12, 0x2c, 0x0a, 0x27, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, + 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x6f, 0x69, 0x6e, + 0x67, 0x41, 0x77, 0x61, 0x79, 0x10, 0x83, 0x1b, 0x12, 0x33, 0x0a, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, - 0x50, 0x75, 0x73, 0x68, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xfa, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x47, 0x6f, 0x61, 0x77, 0x61, 0x79, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x64, 0x10, 0xfb, 0x1a, 0x12, 0x27, 0x0a, 0x22, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x62, 0x6f, 0x72, - 0x74, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x41, 0x70, 0x70, 0x10, 0xfc, 0x1a, 0x12, 0x30, 0x0a, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, + 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x84, 0x1b, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, - 0x46, 0x61, 0x75, 0x6c, 0x74, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0xfd, 0x1a, 0x12, - 0x2e, 0x0a, 0x29, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, - 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x55, - 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0xfe, 0x1a, 0x12, - 0x32, 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, - 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, - 0x10, 0xff, 0x1a, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x10, 0x80, 0x1b, 0x12, 0x32, 0x0a, 0x2d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, - 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x81, 0x1b, 0x12, 0x30, 0x0a, 0x2b, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, - 0x6e, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x82, 0x1b, 0x12, 0x2c, 0x0a, 0x27, 0x44, + 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x85, 0x1b, 0x12, + 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, + 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x44, 0x69, + 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x86, 0x1b, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, - 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x6f, 0x69, - 0x6e, 0x67, 0x41, 0x77, 0x61, 0x79, 0x10, 0x83, 0x1b, 0x12, 0x33, 0x0a, 0x2e, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, - 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, - 0x67, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x84, 0x1b, 0x12, 0x30, - 0x0a, 0x2b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, - 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x44, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x85, 0x1b, - 0x12, 0x2a, 0x0a, 0x25, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, - 0x44, 0x75, 0x6f, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x44, - 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x86, 0x1b, 0x12, 0x1c, 0x0a, 0x17, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x55, 0x78, 0x44, 0x75, 0x6f, 0x46, - 0x61, 0x75, 0x6c, 0x74, 0x45, 0x6e, 0x64, 0x10, 0x87, 0x1b, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, - 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x53, - 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x10, 0x90, 0x1c, 0x12, 0x16, 0x0a, 0x11, - 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, - 0x63, 0x10, 0xd8, 0x1d, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x10, 0xd9, 0x1d, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, - 0x74, 0x70, 0x5f, 0x49, 0x6e, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x10, 0xda, 0x1d, 0x12, 0x1c, 0x0a, 0x17, 0x44, - 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x10, 0xdb, 0x1d, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, - 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x4e, 0x6f, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x10, 0xdc, 0x1d, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, - 0x74, 0x74, 0x70, 0x5f, 0x42, 0x61, 0x64, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x50, 0x61, - 0x74, 0x68, 0x10, 0xdd, 0x1d, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, - 0x74, 0x70, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x10, 0xde, 0x1d, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x4e, 0x6f, 0x53, 0x75, 0x63, 0x68, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x10, 0xdf, - 0x1d, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x50, - 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x48, 0x65, 0x6c, 0x64, 0x10, - 0xe0, 0x1d, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, - 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x49, 0x6d, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x74, - 0x65, 0x10, 0xe1, 0x1d, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x4c, 0x6f, 0x67, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xe2, - 0x1d, 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x4e, - 0x6f, 0x53, 0x75, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x6f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x10, 0xe3, 0x1d, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, - 0x70, 0x5f, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x10, 0xe4, - 0x1d, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x4e, - 0x6f, 0x4c, 0x6f, 0x67, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x10, 0xe5, 0x1d, - 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x54, 0x69, - 0x6d, 0x65, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x41, 0x74, 0x44, 0x63, - 0x10, 0xe6, 0x1d, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, - 0x5f, 0x45, 0x6e, 0x64, 0x10, 0xa0, 0x1f, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2f, - 0x72, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x6c, 0x74, 0x45, 0x6e, 0x64, 0x10, 0x87, 0x1b, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, + 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x53, 0x75, + 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x10, 0x90, 0x1c, 0x12, 0x16, 0x0a, 0x11, 0x44, + 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, + 0x10, 0xd8, 0x1d, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x10, 0xd9, 0x1d, 0x12, 0x24, 0x0a, 0x1f, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, + 0x70, 0x5f, 0x49, 0x6e, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x10, 0xda, 0x1d, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, + 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x48, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x10, 0xdb, 0x1d, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, + 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x4e, 0x6f, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x10, 0xdc, 0x1d, 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, + 0x74, 0x70, 0x5f, 0x42, 0x61, 0x64, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x50, 0x61, 0x74, + 0x68, 0x10, 0xdd, 0x1d, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, + 0x70, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, + 0xde, 0x1d, 0x12, 0x1c, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x4e, 0x6f, 0x53, 0x75, 0x63, 0x68, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x10, 0xdf, 0x1d, + 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x50, 0x72, + 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x48, 0x65, 0x6c, 0x64, 0x10, 0xe0, + 0x1d, 0x12, 0x20, 0x0a, 0x1b, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x43, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x49, 0x6d, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x74, 0x65, + 0x10, 0xe1, 0x1d, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x4c, 0x6f, 0x67, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0xe2, 0x1d, + 0x12, 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x4e, 0x6f, + 0x53, 0x75, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x6f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x10, 0xe3, 0x1d, 0x12, 0x1b, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, + 0x5f, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x10, 0xe4, 0x1d, + 0x12, 0x1d, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x4e, 0x6f, + 0x4c, 0x6f, 0x67, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x10, 0xe5, 0x1d, 0x12, + 0x21, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, 0x54, 0x69, 0x6d, + 0x65, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x41, 0x74, 0x44, 0x63, 0x10, + 0xe6, 0x1d, 0x12, 0x12, 0x0a, 0x0d, 0x44, 0x72, 0x6f, 0x70, 0x5f, 0x48, 0x74, 0x74, 0x70, 0x5f, + 0x45, 0x6e, 0x64, 0x10, 0xa0, 0x1f, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2f, 0x72, + 0x65, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_metadata_windows_proto_rawDescOnce sync.Once - file_metadata_windows_proto_rawDescData = file_metadata_windows_proto_rawDesc + file_pkg_utils_metadata_windows_proto_rawDescOnce sync.Once + file_pkg_utils_metadata_windows_proto_rawDescData = file_pkg_utils_metadata_windows_proto_rawDesc ) -func file_metadata_windows_proto_rawDescGZIP() []byte { - file_metadata_windows_proto_rawDescOnce.Do(func() { - file_metadata_windows_proto_rawDescData = protoimpl.X.CompressGZIP(file_metadata_windows_proto_rawDescData) +func file_pkg_utils_metadata_windows_proto_rawDescGZIP() []byte { + file_pkg_utils_metadata_windows_proto_rawDescOnce.Do(func() { + file_pkg_utils_metadata_windows_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_utils_metadata_windows_proto_rawDescData) }) - return file_metadata_windows_proto_rawDescData + return file_pkg_utils_metadata_windows_proto_rawDescData } -var file_metadata_windows_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_metadata_windows_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_metadata_windows_proto_goTypes = []any{ +var file_pkg_utils_metadata_windows_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_pkg_utils_metadata_windows_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_pkg_utils_metadata_windows_proto_goTypes = []any{ (DNSType)(0), // 0: utils.DNSType (DropReason)(0), // 1: utils.DropReason (*RetinaMetadata)(nil), // 2: utils.RetinaMetadata + nil, // 3: utils.RetinaMetadata.PreviouslyObservedTcpFlagsEntry } -var file_metadata_windows_proto_depIdxs = []int32{ +var file_pkg_utils_metadata_windows_proto_depIdxs = []int32{ 0, // 0: utils.RetinaMetadata.dns_type:type_name -> utils.DNSType 1, // 1: utils.RetinaMetadata.drop_reason:type_name -> utils.DropReason - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 3, // 2: utils.RetinaMetadata.previously_observed_tcp_flags:type_name -> utils.RetinaMetadata.PreviouslyObservedTcpFlagsEntry + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } -func init() { file_metadata_windows_proto_init() } -func file_metadata_windows_proto_init() { - if File_metadata_windows_proto != nil { +func init() { file_pkg_utils_metadata_windows_proto_init() } +func file_pkg_utils_metadata_windows_proto_init() { + if File_pkg_utils_metadata_windows_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_metadata_windows_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_pkg_utils_metadata_windows_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*RetinaMetadata); i { case 0: return &v.state @@ -2338,19 +2386,19 @@ func file_metadata_windows_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_metadata_windows_proto_rawDesc, + RawDescriptor: file_pkg_utils_metadata_windows_proto_rawDesc, NumEnums: 2, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_metadata_windows_proto_goTypes, - DependencyIndexes: file_metadata_windows_proto_depIdxs, - EnumInfos: file_metadata_windows_proto_enumTypes, - MessageInfos: file_metadata_windows_proto_msgTypes, + GoTypes: file_pkg_utils_metadata_windows_proto_goTypes, + DependencyIndexes: file_pkg_utils_metadata_windows_proto_depIdxs, + EnumInfos: file_pkg_utils_metadata_windows_proto_enumTypes, + MessageInfos: file_pkg_utils_metadata_windows_proto_msgTypes, }.Build() - File_metadata_windows_proto = out.File - file_metadata_windows_proto_rawDesc = nil - file_metadata_windows_proto_goTypes = nil - file_metadata_windows_proto_depIdxs = nil + File_pkg_utils_metadata_windows_proto = out.File + file_pkg_utils_metadata_windows_proto_rawDesc = nil + file_pkg_utils_metadata_windows_proto_goTypes = nil + file_pkg_utils_metadata_windows_proto_depIdxs = nil } diff --git a/pkg/utils/metadata_windows.proto b/pkg/utils/metadata_windows.proto index 02c9c53e4a..2139f3721e 100644 --- a/pkg/utils/metadata_windows.proto +++ b/pkg/utils/metadata_windows.proto @@ -15,6 +15,11 @@ message RetinaMetadata { // Drop reason in Retina. DropReason drop_reason = 5; + + // Sampling metadata, for packetparser. + uint32 previously_observed_packets = 6; + uint32 previously_observed_bytes = 7; + map previously_observed_tcp_flags = 8; } enum DNSType { From 34bdd195df5a9afa0722ae5353a13db0305a663a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 09:54:08 -0400 Subject: [PATCH 084/448] chore(deps): bump the npm_and_yarn group across 1 directory with 2 updates (#1755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 2 updates in the /site directory: [on-headers](https://github.com/jshttp/on-headers) and [compression](https://github.com/expressjs/compression). Updates `on-headers` from 1.0.2 to 1.1.0
Release notes

Sourced from on-headers's releases.

1.1.0

Important

What's Changed

New Contributors

Full Changelog: https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0

Changelog

Sourced from on-headers's changelog.

1.1.0 / 2025-07-17

Commits
  • 4b017af 1.1.0
  • b636f2d ♻️ refactor header array code
  • 3e2c2d4 ✨ ignore falsy header keys, matching node behavior
  • 172eb41 ✨ support duplicate headers
  • c6e3849 🔒️ fix array handling
  • 6893518 💚 update CI - add newer node versions
  • 56a345d ✨ add script to update known hashes
  • 175ab21 👷 add upstream change detection (#31)
  • ce0b2c8 ci: apply OSSF Scorecard security best practices (#20)
  • 1a38c54 fix: use ubuntu-latest as ci runner (#19)
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by ulisesgascon, a new releaser for on-headers since your current version.


Updates `compression` from 1.7.5 to 1.8.1
Release notes

Sourced from compression's releases.

v1.8.1

What's Changed

New Contributors

Full Changelog: https://github.com/expressjs/compression/compare/1.8.0...v1.8.1

v1.8.0

What's Changed

New Contributors

Full Changelog: https://github.com/expressjs/compression/compare/1.7.5...v1.8.0

Changelog

Sourced from compression's changelog.

1.8.1 / 2025-07-17

1.8.0 / 2025-02-10

  • Use res.headersSent when available
  • Replace _implicitHeader with writeHead property
  • add brotli support for versions of node that support it
  • Add the enforceEncoding option for requests without Accept-Encoding header
Commits
  • 83a0c45 1.8.1
  • ce62713 deps: on-headers@1.1.0 (#246)
  • f4acb23 build(deps-dev): bump eslint-plugin-import from 2.31.0 to 2.32.0 (#244)
  • 6eaebe6 build(deps): bump actions/checkout from 4.1.1 to 4.2.2 (#241)
  • 37e0623 build(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.2 (#240)
  • bc436b2 build(deps): bump actions/upload-artifact from 4.3.1 to 4.6.2 (#239)
  • 2f9f572 build(deps): bump github/codeql-action from 3.28.15 to 3.29.2 (#243)
  • 5f13b14 [StepSecurity] ci: Harden GitHub Actions (#235)
  • 76e0945 build(deps-dev): bump supertest from 6.2.3 to 6.3.4 (#231)
  • ae6ee80 build(deps-dev): bump eslint-plugin-import from 2.26.0 to 2.31.0 (#230)
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index b3e0223df3..3a5d4cd151 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -6740,16 +6740,16 @@ } }, "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -13437,9 +13437,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { "node": ">= 0.8" From dbafe30ce09b0e675301277bcac81940f40668ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 11:26:27 -0400 Subject: [PATCH 085/448] deps: bump sigstore/cosign-installer from 3.9.1 to 3.9.2 (#1756) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.9.1 to 3.9.2.
Release notes

Sourced from sigstore/cosign-installer's releases.

v3.9.2

What's Changed

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v3.9.1...v3.9.2

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=3.9.1&new-version=3.9.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index a8fdd51113..6334078a04 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -27,7 +27,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index cc0d574790..5c0fc217ea 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -32,7 +32,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -78,7 +78,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -124,7 +124,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -169,7 +169,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -212,7 +212,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -260,7 +260,7 @@ jobs: uses: docker/setup-qemu-action@v3 - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@v3.9.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From 773a3365c34bef39427e2d378ee8f87608b91fb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 11:26:41 -0400 Subject: [PATCH 086/448] deps: bump github.com/spf13/pflag from 1.0.6 to 1.0.7 (#1757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.6 to 1.0.7.
Release notes

Sourced from github.com/spf13/pflag's releases.

v1.0.7

What's Changed

New Contributors

Full Changelog: https://github.com/spf13/pflag/compare/v1.0.6...v1.0.7

Commits
  • f9cbdd9 Merge pull request #348 from max-frank/add-time-flag-support
  • e3be2eb Reduce duplication by forwarding to sibling functions
  • 7cc25e3 Don't export TimeValue (yet)
  • d15848d Remove unnecessary time test stderr dev null redirect
  • c5ce22e Use time.Time for expectations in time flag tests
  • 1992c5a Add support for time.Time flags
  • 1c62fb2 Merge pull request #431 from LeGEC/430-fix-usage-message-for-func-flags
  • 1a4b5b2 fix discrepancy in order of arguments for Func() and BoolFunc() #433
  • 4730aa0 fix help message for Func and BoolFunc flags #430
  • f4c97c2 minor: fix typos in comments
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/spf13/pflag&package-manager=go_modules&previous-version=1.0.6&new-version=1.0.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 4ff04bbb9f..4b307c0a6a 100644 --- a/go.mod +++ b/go.mod @@ -238,7 +238,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/spf13/pflag v1.0.6 + github.com/spf13/pflag v1.0.7 github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.42.0 // indirect diff --git a/go.sum b/go.sum index 5ec1c627cd..2bb1048fad 100644 --- a/go.sum +++ b/go.sum @@ -1372,8 +1372,9 @@ github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cA github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= From cc4c1b8efa5b064bfd760a9dcb463f357c2e5ddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 14:50:21 -0400 Subject: [PATCH 087/448] chore(deps): bump golang.org/x/oauth2 from 0.10.0 to 0.27.0 in /hack/tools/kapinger in the go_modules group across 1 directory (#1758) Bumps the go_modules group with 1 update in the /hack/tools/kapinger directory: [golang.org/x/oauth2](https://github.com/golang/oauth2). Updates `golang.org/x/oauth2` from 0.10.0 to 0.27.0
Commits
  • 681b4d8 jws: split token into fixed number of parts
  • 3f78298 all: upgrade go directive to at least 1.23.0 [generated]
  • 109dabf endpoints: add links/provider for Discord
  • ac571fa oauth2: fix docs for Config.DeviceAuth
  • 314ee5b endpoints: add patreon endpoint
  • b9c813b google: add warning about externally-provided credentials
  • 49a531d all: make method and struct comments match the names
  • 22134a4 README: don't recommend go get
  • 3e64809 x/oauth2: add Token.ExpiresIn
  • 16a9973 jwt: rename example to avoid vet error
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.10.0&new-version=0.27.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/tools/kapinger/go.mod | 3 +-- hack/tools/kapinger/go.sum | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/hack/tools/kapinger/go.mod b/hack/tools/kapinger/go.mod index 76613ef5c8..225994b5b1 100644 --- a/hack/tools/kapinger/go.mod +++ b/hack/tools/kapinger/go.mod @@ -28,12 +28,11 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect golang.org/x/net v0.38.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect + golang.org/x/oauth2 v0.27.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/term v0.30.0 // indirect golang.org/x/text v0.23.0 // indirect golang.org/x/time v0.3.0 // indirect - google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/hack/tools/kapinger/go.sum b/hack/tools/kapinger/go.sum index 55c50da34a..91728dde65 100644 --- a/hack/tools/kapinger/go.sum +++ b/hack/tools/kapinger/go.sum @@ -16,7 +16,6 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -80,14 +79,13 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -101,7 +99,6 @@ golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= @@ -117,8 +114,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From b8a385f0e553b7c9f52be2b8c56e219b1e7c96e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Jul 2025 11:37:46 -0400 Subject: [PATCH 088/448] chore(deps): bump golang.org/x/oauth2 from 0.24.0 to 0.27.0 in /test/multicloud/test in the go_modules group across 1 directory (#1759) Bumps the go_modules group with 1 update in the /test/multicloud/test directory: [golang.org/x/oauth2](https://github.com/golang/oauth2). Updates `golang.org/x/oauth2` from 0.24.0 to 0.27.0
Commits
  • 681b4d8 jws: split token into fixed number of parts
  • 3f78298 all: upgrade go directive to at least 1.23.0 [generated]
  • 109dabf endpoints: add links/provider for Discord
  • ac571fa oauth2: fix docs for Config.DeviceAuth
  • 314ee5b endpoints: add patreon endpoint
  • b9c813b google: add warning about externally-provided credentials
  • 49a531d all: make method and struct comments match the names
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.24.0&new-version=0.27.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/multicloud/test/go.mod | 2 +- test/multicloud/test/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/multicloud/test/go.mod b/test/multicloud/test/go.mod index e872f06bf7..68c50cc8ec 100644 --- a/test/multicloud/test/go.mod +++ b/test/multicloud/test/go.mod @@ -56,7 +56,7 @@ require ( golang.org/x/crypto v0.36.0 // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.38.0 // indirect - golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/oauth2 v0.27.0 // indirect golang.org/x/sync v0.12.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/term v0.30.0 // indirect diff --git a/test/multicloud/test/go.sum b/test/multicloud/test/go.sum index a27d7ceaf5..3e1d421d91 100644 --- a/test/multicloud/test/go.sum +++ b/test/multicloud/test/go.sum @@ -144,8 +144,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 5a50477c0f8da36132b50ef04463aa5e26846e36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Jul 2025 15:44:44 +0000 Subject: [PATCH 089/448] deps: bump google.golang.org/grpc from 1.73.0 to 1.74.0 (#1750) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.74.0.
Release notes

Sourced from google.golang.org/grpc's releases.

Release 1.74.0 was accidentally tagged on the wrong commit and will be deleted. Please update to 1.74.1 which should be released shortly.

Commits
  • 406c2bf transport: release mutex before returning on expired deadlines in server stre...
  • 20ef77a xds: give up pool lock before closing xdsclient channel (#8445)
  • 2f9bb38 xdsclient: relay marshalled bytes of complete resource proto to decoders (#8422)
  • fa3ec85 xds: Avoid error logs when setting fallback bootstrap config (#8419)
  • d307d75 xdsclient: preserve original bytes for decoding when the resource is wrapped ...
  • b34f845 server: allow 0s grpc-timeout header values, as java is known to be able to s...
  • 1787f94 xdsclient: export genericResourceTypeDecoder (#8406)
  • 15299cc xdsclient: make a function to return the supported resource type implementati...
  • 20bd1e7 grpc: revert #8278: Fix cardinality violations in non-server streaming RPCs (...
  • bdbe6a2 examples/opentelemetry: demonstrate enabling experimental metrics (#8388)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.73.0&new-version=1.74.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 4b307c0a6a..066b37bdc6 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ retract ( ) require ( - cel.dev/expr v0.23.0 // indirect + cel.dev/expr v0.24.0 // indirect code.cloudfoundry.org/clock v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect @@ -67,7 +67,7 @@ require ( github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a // indirect github.com/cilium/lumberjack/v2 v2.4.1 // indirect github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect - github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect + github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/containerd v1.7.27 // indirect github.com/containerd/continuity v0.4.4 // indirect @@ -217,8 +217,8 @@ require ( golang.org/x/tools v0.34.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/apiserver v0.32.3 // indirect k8s.io/component-base v0.32.3 // indirect @@ -306,7 +306,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - google.golang.org/grpc v1.73.0 + google.golang.org/grpc v1.74.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 @@ -337,7 +337,7 @@ require ( cloud.google.com/go v0.116.0 // indirect cloud.google.com/go/auth v0.15.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/compute/metadata v0.7.0 // indirect cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/kms v1.20.1 // indirect cloud.google.com/go/longrunning v0.6.2 // indirect @@ -629,13 +629,13 @@ require ( go-simpler.org/musttag v0.13.0 // indirect go-simpler.org/sloglint v0.9.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect diff --git a/go.sum b/go.sum index 2bb1048fad..df29eef6f9 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ 4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= -cel.dev/expr v0.23.0 h1:wUb94w6OYQS4uXraxo9U+wUAs9jT47Xvl4iPgAwM2ss= -cel.dev/expr v0.23.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= @@ -12,8 +12,8 @@ cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= cloud.google.com/go/kms v1.20.1 h1:og29Wv59uf2FVaZlesaiDAqHFzHaoUyHI3HYp9VUHVg= @@ -407,8 +407,8 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f h1:C5bqEmzEPLsHm9Mv73lSE9e9bKV23aB1vxOsmZrkl3k= -github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -1525,8 +1525,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0 h1:x7sPooQCwSg27SjtQee8GyIIRTQcF4s7eSkac6F2+VA= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0/go.mod h1:4K5UXgiHxV484efGs42ejD7E2J/sIlepYgdGoPXe7hE= -go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA= -go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 h1:GuQXpvSXNjpswpweIem84U9BNauqHHi2w1GtNAalvpM= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0/go.mod h1:CkmxekdHco4d7thFJNPQ7Mby4jMBgZUclnrxT4e+ryk= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= @@ -1561,12 +1561,12 @@ go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDT go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -1858,10 +1858,10 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= 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= @@ -1870,8 +1870,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= +google.golang.org/grpc v1.74.0 h1:sxRSkyLxlceWQiqDofxDot3d4u7DyoHPc7SBXMj8gGY= +google.golang.org/grpc v1.74.0/go.mod h1:NZUaK8dAMUfzhK6uxZ+9511LtOrk73UGWOFoNvz7z+s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 78dfd9e6f78b51834bf49e0e537fa9260b015207 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Jul 2025 19:50:56 -0400 Subject: [PATCH 090/448] deps: bump helm.sh/helm/v3 from 3.17.3 to 3.18.4 in the go_modules group (#1737) Bumps the go_modules group with 1 update: [helm.sh/helm/v3](https://github.com/helm/helm). Updates `helm.sh/helm/v3` from 3.17.3 to 3.18.4
Release notes

Sourced from helm.sh/helm/v3's releases.

Helm v3.18.4 is a security release. Users are encouraged to upgrade for the best experience.

The community keeps growing, and we'd love to see you there!

  • Join the discussion in Kubernetes Slack:
    • for questions and just to hang out
    • for discussing PRs, code, and bugs
  • Hang out at the Public Developer Call: Thursday, 9:30 Pacific via Zoom
  • Test, debug, and contribute charts: ArtifactHub/packages

Installation and Upgrading

Download Helm v3.18.4. The common platform binaries are here:

The Quickstart Guide will get you going from there. For upgrade instructions or detailed installation notes, check the install guide. You can also use a script to install on any system with bash.

What's Next

  • 3.18.5 is the next patch release and will be on August 13, 2025
  • 3.19.0 is the next minor release and will be on September 11, 2025

Changelog

  • Disabling linter due to unknown issue f20a4ad1d5c953ca0fb3d3b30aa9aa796d472ef1 (Matt Farina)
  • build(deps): bump the k8s-io group with 7 updates 563b0947b995c48354319aa054830db61f793a08 (dependabot[bot])
  • Updating link handling 00de613324df4dd930e6d231d9aae7f9dee29c76 (Matt Farina)

Helm 3.18.3

Helm v3.18.3 is a patch release. Users are encouraged to upgrade for the best experience. Users are encouraged to upgrade for the best experience.

The community keeps growing, and we'd love to see you there!

  • Join the discussion in Kubernetes Slack:
    • for questions and just to hang out
    • for discussing PRs, code, and bugs
  • Hang out at the Public Developer Call: Thursday, 9:30 Pacific via Zoom
  • Test, debug, and contribute charts: ArtifactHub/packages

... (truncated)

Commits
  • d80839c Merge pull request #31037 from mattfarina/disable-goimports-2
  • f20a4ad Disabling linter due to unknown issue
  • c48c500 Merge commit from fork
  • 563b094 build(deps): bump the k8s-io group with 7 updates
  • 00de613 Updating link handling
  • 6838ebc build(deps): bump golang.org/x/crypto from 0.38.0 to 0.39.0
  • 5b9e2f6 fix: user username password for login
  • 2782412 Update pkg/registry/transport.go
  • e66cf6a Update pkg/registry/transport.go
  • 191f05c fix: add debug logging to oci transport
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=helm.sh/helm/v3&package-manager=go_modules&previous-version=3.17.3&new-version=3.18.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 066b37bdc6..1aaa290502 100644 --- a/go.mod +++ b/go.mod @@ -310,7 +310,7 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 - helm.sh/helm/v3 v3.17.3 + helm.sh/helm/v3 v3.17.4 k8s.io/apiextensions-apiserver v0.32.3 k8s.io/cli-runtime v0.32.3 k8s.io/kubectl v0.32.3 diff --git a/go.sum b/go.sum index df29eef6f9..16f3cff1d1 100644 --- a/go.sum +++ b/go.sum @@ -1929,8 +1929,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -helm.sh/helm/v3 v3.17.3 h1:3n5rW3D0ArjFl0p4/oWO8IbY/HKaNNwJtOQFdH2AZHg= -helm.sh/helm/v3 v3.17.3/go.mod h1:+uJKMH/UiMzZQOALR3XUf3BLIoczI2RKKD6bMhPh4G8= +helm.sh/helm/v3 v3.17.4 h1:GK+vgn9gKCyoH44+f3B5zpA78iH3AK4ywIInDEmmn/g= +helm.sh/helm/v3 v3.17.4/go.mod h1:+uJKMH/UiMzZQOALR3XUf3BLIoczI2RKKD6bMhPh4G8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= From 0f2c72bba3dd394d67d4d02023c49cff9ec3f626 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:51:31 +0000 Subject: [PATCH 091/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.83.0 to 1.84.0 (#1747) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.83.0 to 1.84.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.83.0&new-version=1.84.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1aaa290502..5a070144e3 100644 --- a/go.mod +++ b/go.mod @@ -275,7 +275,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.36.5 github.com/aws/aws-sdk-go-v2/config v1.29.17 github.com/aws/aws-sdk-go-v2/credentials v1.17.70 - github.com/aws/aws-sdk-go-v2/service/s3 v1.83.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.84.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 16f3cff1d1..998007f897 100644 --- a/go.sum +++ b/go.sum @@ -274,8 +274,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 h1:qcLWgdhq45sDM github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17/go.mod h1:M+jkjBFZ2J6DJrjMv2+vkBbuht6kxJYtJiwoVgX4p4U= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.83.0 h1:5Y75q0RPQoAbieyOuGLhjV9P3txvYgXv2lg0UwJOfmE= -github.com/aws/aws-sdk-go-v2/service/s3 v1.83.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.0 h1:0reDqfEN+tB+sozj2r92Bep8MEwBZgtAXTND1Kk9OXg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= From 75fc276212c5677d1f00d6ef49c6e3551683893f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:08:53 -0400 Subject: [PATCH 092/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.84.0 to 1.84.1 (#1765) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.84.0 to 1.84.1.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.84.0&new-version=1.84.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 5a070144e3..21cab0c9c5 100644 --- a/go.mod +++ b/go.mod @@ -48,14 +48,14 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect @@ -272,10 +272,10 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.36.5 + github.com/aws/aws-sdk-go-v2 v1.36.6 github.com/aws/aws-sdk-go-v2/config v1.29.17 github.com/aws/aws-sdk-go-v2/credentials v1.17.70 - github.com/aws/aws-sdk-go-v2/service/s3 v1.84.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 998007f897..f46afc3fbe 100644 --- a/go.sum +++ b/go.sum @@ -240,8 +240,8 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= -github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU= +github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= @@ -252,30 +252,30 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6Wm github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 h1:GMYy2EOWfzdP3wfVAGXBNKY5vK4K8vMET4sYOYltmqs= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36/go.mod h1:gDhdAV6wL3PmPqBhiPbnlS447GoWs8HTTOYef9/9Inw= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37/go.mod h1:Pi6ksbniAWVwu2S8pEzcYPyhUkAcLaufxN7PfAUQjBk= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 h1:nAP2GYbfh8dd2zGZqFRSMlq+/F6cMPBUuCsGAMkN074= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4/go.mod h1:LT10DsiGjLWh4GbjInf9LQejkYEhBgBCjLG5+lvk4EE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 h1:qcLWgdhq45sDM9na4cvXax9dyLitn8EYBRl8Ak4XtG4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17/go.mod h1:M+jkjBFZ2J6DJrjMv2+vkBbuht6kxJYtJiwoVgX4p4U= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.84.0 h1:0reDqfEN+tB+sozj2r92Bep8MEwBZgtAXTND1Kk9OXg= -github.com/aws/aws-sdk-go-v2/service/s3 v1.84.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= From 1983b55c0fca562a938140b42c9f05c1d1c3e58d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 15:44:58 -0400 Subject: [PATCH 093/448] deps: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.70 to 1.17.71 (#1764) Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.70 to 1.17.71.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/credentials&package-manager=go_modules&previous-version=1.17.70&new-version=1.17.71)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 21cab0c9c5..cc3b978ff4 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect @@ -56,9 +56,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect github.com/aws/smithy-go v1.22.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 @@ -274,7 +274,7 @@ require ( github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.36.6 github.com/aws/aws-sdk-go-v2/config v1.29.17 - github.com/aws/aws-sdk-go-v2/credentials v1.17.70 + github.com/aws/aws-sdk-go-v2/credentials v1.17.71 github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 diff --git a/go.sum b/go.sum index f46afc3fbe..789aca6965 100644 --- a/go.sum +++ b/go.sum @@ -246,10 +246,10 @@ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGk github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= -github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0= -github.com/aws/aws-sdk-go-v2/credentials v1.17.70/go.mod h1:M+lWhhmomVGgtuPOhO85u4pEa3SmssPTdcYpP/5J/xc= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6WmlVKLFFXgWYAGoJosorxzU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33/go.mod h1:caS/m4DI+cij2paz3rtProRBI4s/+TCiWoaWZuQ9010= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= @@ -276,12 +276,12 @@ github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vs github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E= -github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0= -github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 h1:rGtWqkQbPk7Bkwuv3NzpE/scwwL9sC1Ul3tn9x83DUI= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6/go.mod h1:u4ku9OLv4TO4bCPdxf4fA1upaMaJmP9ZijGk3AAOC6Q= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWdumLxNbzz1P0zJoezkJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= From 4e775c78327176db2095e0fba25f2fd5a5dd3481 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 09:49:28 -0400 Subject: [PATCH 094/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.29.17 to 1.29.18 (#1761) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.29.17 to 1.29.18.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.29.17&new-version=1.29.18)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cc3b978ff4..555ed4e293 100644 --- a/go.mod +++ b/go.mod @@ -273,7 +273,7 @@ require ( github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.36.6 - github.com/aws/aws-sdk-go-v2/config v1.29.17 + github.com/aws/aws-sdk-go-v2/config v1.29.18 github.com/aws/aws-sdk-go-v2/credentials v1.17.71 github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 diff --git a/go.sum b/go.sum index 789aca6965..9055a06d66 100644 --- a/go.sum +++ b/go.sum @@ -244,8 +244,8 @@ github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQ github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= -github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= -github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= +github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= +github.com/aws/aws-sdk-go-v2/config v1.29.18/go.mod h1:bvz8oXugIsH8K7HLhBv06vDqnFv3NsGDt2Znpk7zmOU= github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= From c94f5623a63d6ab5b38c806addc3bdc7276110ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 11:47:23 -0400 Subject: [PATCH 095/448] deps: bump github.com/onsi/gomega from 1.37.0 to 1.38.0 (#1770) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.37.0 to 1.38.0.
Release notes

Sourced from github.com/onsi/gomega's releases.

v1.38.0

1.38.0

Features

  • gstruct handles extra unexported fields [4ee7ed0]

Fixes

  • support [] in IgnoringTopFunction function signatures (#851) [36bbf72]

Maintenance

  • Bump golang.org/x/net from 0.40.0 to 0.41.0 (#846) [529d408]
  • Fix typo [acd1f55]
  • Bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#835) [bae65a0]
  • Bump nokogiri from 1.18.4 to 1.18.8 in /docs (#842) [8dda91f]
  • Bump golang.org/x/net from 0.39.0 to 0.40.0 (#843) [212d812]
  • Bump github.com/onsi/ginkgo/v2 from 2.23.3 to 2.23.4 (#839) [59bd7f9]
  • Bump nokogiri from 1.18.1 to 1.18.4 in /docs (#834) [328c729]
  • Bump uri from 1.0.2 to 1.0.3 in /docs (#826) [9a798a1]
  • Bump golang.org/x/net from 0.37.0 to 0.39.0 (#841) [04a72c6]
Changelog

Sourced from github.com/onsi/gomega's changelog.

1.38.0

Features

  • gstruct handles extra unexported fields [4ee7ed0]

Fixes

  • support [] in IgnoringTopFunction function signatures (#851) [36bbf72]

Maintenance

  • Bump golang.org/x/net from 0.40.0 to 0.41.0 (#846) [529d408]
  • Fix typo [acd1f55]
  • Bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#835) [bae65a0]
  • Bump nokogiri from 1.18.4 to 1.18.8 in /docs (#842) [8dda91f]
  • Bump golang.org/x/net from 0.39.0 to 0.40.0 (#843) [212d812]
  • Bump github.com/onsi/ginkgo/v2 from 2.23.3 to 2.23.4 (#839) [59bd7f9]
  • Bump nokogiri from 1.18.1 to 1.18.4 in /docs (#834) [328c729]
  • Bump uri from 1.0.2 to 1.0.3 in /docs (#826) [9a798a1]
  • Bump golang.org/x/net from 0.37.0 to 0.39.0 (#841) [04a72c6]
Commits
  • c1237df v1.38.0
  • 36bbf72 support [] in IgnoringTopFunction function signatures (#851)
  • 4ee7ed0 gstruct handles extra unexported fields
  • 529d408 Bump golang.org/x/net from 0.40.0 to 0.41.0 (#846)
  • acd1f55 Fix typo
  • bae65a0 Bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#835)
  • 8dda91f Bump nokogiri from 1.18.4 to 1.18.8 in /docs (#842)
  • 212d812 Bump golang.org/x/net from 0.39.0 to 0.40.0 (#843)
  • 59bd7f9 Bump github.com/onsi/ginkgo/v2 from 2.23.3 to 2.23.4 (#839)
  • 328c729 Bump nokogiri from 1.18.1 to 1.18.4 in /docs (#834)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/onsi/gomega&package-manager=go_modules&previous-version=1.37.0&new-version=1.38.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 555ed4e293..50d5258c95 100644 --- a/go.mod +++ b/go.mod @@ -293,7 +293,7 @@ require ( github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.0 github.com/onsi/ginkgo/v2 v2.23.4 - github.com/onsi/gomega v1.37.0 + github.com/onsi/gomega v1.38.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.65.0 diff --git a/go.sum b/go.sum index 9055a06d66..1476112f76 100644 --- a/go.sum +++ b/go.sum @@ -1187,8 +1187,8 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= -github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= +github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= 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.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= From 876d56a96ee91743577e757b30a2fe97b78627b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 22:02:08 +0000 Subject: [PATCH 096/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.6.1 to 1.6.2 (#1773) Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.6.1 to 1.6.2.
Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/storage/azblob's releases.

sdk/storage/azblob/v1.6.2

1.6.2 (2025-07-23)

Other Changes

  • Updated azcore version to 1.18.1

sdk/storage/azblob/v1.6.2-beta.2

1.6.2-beta.2 (2025-07-08)

Other Changes

  • Updated azidentity version to 1.10.1

sdk/storage/azblob/v1.6.2-beta.1

1.6.2-beta.1 (2025-05-08)

Features Added

  • Add support for x-ms-file-request-intent header for blob copy APIs.
Commits
  • 5b7ca8c changelog and go mod updates for release (#24990)
  • 9e1e134 fix identity dep version (#24986)
  • 7418f66 [Release] sdk/resourcemanager/recoveryservicesdatareplication/armrecoveryserv...
  • 72cfa13 update version (#24985)
  • 114ed10 [azopenai] Update deps, point to latest in main, and regen. (#24982)
  • bbbf16c [Release] sdk/resourcemanager/providerhub/armproviderhub/2.0.0 generation fro...
  • bc4b735 [Release] sdk/resourcemanager/carbonoptimization/armcarbonoptimization/1.0.0 ...
  • 0cc45a3 [Release] sdk/resourcemanager/storagediscovery/armstoragediscovery/0.1.0 gene...
  • e80945a update version (#24969)
  • 43928aa Remove import to v1 module (#24963)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/storage/azblob&package-manager=go_modules&previous-version=1.6.1&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 50d5258c95..f6db403ee0 100644 --- a/go.mod +++ b/go.mod @@ -117,7 +117,7 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.3 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.9 // indirect @@ -269,7 +269,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.36.6 diff --git a/go.sum b/go.sum index 1476112f76..8559a81d9b 100644 --- a/go.sum +++ b/go.sum @@ -109,8 +109,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 h1:FwladfywkNirM+FZYLBR2kBz5C8Tg0fw5w5Y7meRXWI= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2/go.mod h1:vv5Ad0RrIoT1lJFdWBZwt4mB1+j+V8DUroixmKDTCdk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -684,8 +684,8 @@ github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= +github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= From 183c0997455c0ba5c7dadf4fe8757e910198c3ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 11:05:51 -0400 Subject: [PATCH 097/448] deps: bump sigs.k8s.io/yaml from 1.5.0 to 1.6.0 (#1774) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.5.0 to 1.6.0.
Release notes

Sourced from sigs.k8s.io/yaml's releases.

v1.6.0

What's Changed

Commits
  • 048d724 Merge pull request #132 from thockin/master
  • 23c836c Bolster tests, mostly in error-handling
  • 2e3340b Add compact output tests
  • 4a4f539 Add test case for tabs in multi-line strings
  • 13509ad Change which methods get a newline and fix tests
  • 59c2c43 Add compact mode so KYAML can be used in more places
  • abc1add kyaml: Implement escaping closer to YAML spec
  • 7749171 Add a yamlfmt cmd
  • a932007 Add KYAML support
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/yaml&package-manager=go_modules&previous-version=1.5.0&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f6db403ee0..33b2f98689 100644 --- a/go.mod +++ b/go.mod @@ -255,7 +255,7 @@ require ( k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect - sigs.k8s.io/yaml v1.5.0 + sigs.k8s.io/yaml v1.6.0 ) require ( diff --git a/go.sum b/go.sum index 8559a81d9b..e14bbd8742 100644 --- a/go.sum +++ b/go.sum @@ -2000,7 +2000,7 @@ sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxO sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= From 335c6dbb46a4bec20303f445a5b1c4d5c368c4d7 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:09:26 +0000 Subject: [PATCH 098/448] fix: pcap file name formatting (#1749) # Description Fix the bad formatting of the pcap file names when running `retina capture create`. Also adding testing for the utilities around how file names are created. ## Related Issue https://github.com/microsoft/retina/issues/1732 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed {D77C22CD-6FFA-44A0-B15B-B89E4542A2A2} The below shows a successful download of a packet capture which is then extracted. The final grep shows the file name of the `.pcap` which is in the same format as the `.tar.gz`. ``` ~/src/retina git:kamilp/capture-filename-format > k retina capture download --name pcap-filename -o ./downloads File to be downloaded: /host/mnt/retina/captures/pcap-filename-aks-agentpool-33289083-vmss000000-20250716220911UTC.tar.gz Creating download pod: pcap-filename-download-d49wc Obtaining file... Bytes retrieved: 189453 File written to: downloads/pcap-filename/pcap-filename-aks-agentpool-33289083-vmss000000-20250716220911UTC.tar.gz File to be downloaded: /host/mnt/retina/captures/pcap-filename-aks-agentpool-33289083-vmss000001-20250716220911UTC.tar.gz Creating download pod: pcap-filename-download-t86dl Obtaining file... Bytes retrieved: 277310 File written to: downloads/pcap-filename/pcap-filename-aks-agentpool-33289083-vmss000001-20250716220911UTC.tar.gz ~/src/retina git:kamilp/capture-filename-format* > cd ./downloads/ ~/src/retina/downloads git:kamilp/capture-filename-format* > mkdir extract ~/src/retina/downloads git:kamilp/capture-filename-format* > tar -xvf pcap-filename/pcap-filename-aks-agentpool-33289083-vmss000001-20250716220911UTC.tar.gz -C extract/ ~/src/retina/downloads git:kamilp/capture-filename-format* > cd extract/ ~/src/retina/downloads/extract git:kamilp/capture-filename-format* > ll | grep ".pcap" .rw-r--r-- kamilp 557 KB 2025-07-16 23:09:23 pcap-filename-aks-agentpool-33289083-vmss000001-20250716220911UTC.pcap --------- Signed-off-by: Kamil --- pkg/capture/file/capture_filename_test.go | 84 +++++++++ pkg/capture/file/timestamp.go | 7 +- pkg/capture/file/timestamp_test.go | 185 +++++++++++++++++++ pkg/capture/provider/network_capture_unix.go | 2 +- 4 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 pkg/capture/file/capture_filename_test.go create mode 100644 pkg/capture/file/timestamp_test.go diff --git a/pkg/capture/file/capture_filename_test.go b/pkg/capture/file/capture_filename_test.go new file mode 100644 index 0000000000..fc2327d4da --- /dev/null +++ b/pkg/capture/file/capture_filename_test.go @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package file + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestCaptureFilenameFormat(t *testing.T) { + tests := []struct { + name string + captureName string + nodeHostname string + timestamp *v1.Time + expected string + }{ + { + name: "valid filename", + captureName: "capture-name", + nodeHostname: "node1", + timestamp: &v1.Time{Time: time.Date(2025, 1, 1, 12, 30, 0, 0, time.UTC)}, + expected: "capture-name-node1-20250101123000UTC", + }, + { + name: "different timezone", + captureName: "capture-name", + nodeHostname: "node1", + timestamp: &v1.Time{Time: time.Date(2025, 1, 1, 8, 30, 0, 0, time.FixedZone("EDT", -4*60*60))}, // 8:30 EDT is 12:30 UTC + expected: "capture-name-node1-20250101123000UTC", + }, + { + name: "empty capture name", + captureName: "", + nodeHostname: "node1", + timestamp: &v1.Time{Time: time.Date(2025, 1, 1, 12, 30, 0, 0, time.UTC)}, + expected: "-node1-20250101123000UTC", + }, + { + name: "empty node name", + captureName: "capture-name", + nodeHostname: "", + timestamp: &v1.Time{Time: time.Date(2025, 1, 1, 12, 30, 0, 0, time.UTC)}, + expected: "capture-name--20250101123000UTC", + }, + { + name: "zero time", + captureName: "capture-name", + nodeHostname: "node1", + timestamp: &v1.Time{Time: time.Time{}}, + expected: "capture-name-node1-00010101000000UTC", + }, + { + name: "nil timestamp", + captureName: "capture-name", + nodeHostname: "node1", + timestamp: nil, + expected: "capture-name-node1-00010101000000UTC", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + filename := CaptureFilename{ + CaptureName: tt.captureName, + NodeHostname: tt.nodeHostname, + StartTimestamp: tt.timestamp, + } + + // .String() here relies on TimeToString(), which should handle nil timestamps gracefully + // and return a zero time string - this should not panic + var result string + assert.NotPanics(t, func() { + result = filename.String() + }, "CaptureFilename.String() should handle nil timestamp gracefully") + + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/pkg/capture/file/timestamp.go b/pkg/capture/file/timestamp.go index 553dcafc01..946a0fc945 100644 --- a/pkg/capture/file/timestamp.go +++ b/pkg/capture/file/timestamp.go @@ -23,6 +23,11 @@ func StringToTime(timestamp string) (*metav1.Time, error) { } // Converts a metav1.Time to a string in the capture file name format +// Returns a zero time string if timestamp is nil +// Converts to UTC if other timezone is provided func TimeToString(timestamp *metav1.Time) string { - return timestamp.Format(captureFileNameTimestampFormat) + if timestamp == nil { + return (&metav1.Time{Time: time.Time{}}).Format(captureFileNameTimestampFormat) + } + return timestamp.UTC().Format(captureFileNameTimestampFormat) } diff --git a/pkg/capture/file/timestamp_test.go b/pkg/capture/file/timestamp_test.go new file mode 100644 index 0000000000..21ad85a3bb --- /dev/null +++ b/pkg/capture/file/timestamp_test.go @@ -0,0 +1,185 @@ +package file + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestNow(t *testing.T) { + before := time.Now().UTC().Truncate(time.Second) + result := Now() + after := time.Now().UTC().Truncate(time.Second) + + require.NotNil(t, result) + assert.GreaterOrEqual(t, result.Time, before) + assert.LessOrEqual(t, result.Time, after) + assert.Equal(t, 0, result.Time.Nanosecond()) // ensure timestamp is truncated +} + +func TestStringToTime(t *testing.T) { + tests := []struct { + name string + input string + expected *metav1.Time + wantError bool + }{ + { + name: "valid timestamp", + input: "20250101120000UTC", + expected: &metav1.Time{Time: time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)}, + wantError: false, + }, + { + name: "another valid timestamp", + input: "20251231235959UTC", + expected: &metav1.Time{Time: time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)}, + wantError: false, + }, + { + name: "midnight timestamp", + input: "20250101000000UTC", + expected: &metav1.Time{Time: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)}, + wantError: false, + }, + { + name: "invalid format", + input: "2025-01-01 12:00:00", + expected: nil, + wantError: true, + }, + { + name: "empty string", + input: "", + expected: nil, + wantError: true, + }, + { + name: "invalid month", + input: "20251301120000UTC", + expected: nil, + wantError: true, + }, + { + name: "invalid day", + input: "20250132120000UTC", + expected: nil, + wantError: true, + }, + { + name: "invalid hour", + input: "20250101250000UTC", + expected: nil, + wantError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := StringToTime(tt.input) + if tt.wantError { + require.Error(t, err) + assert.Nil(t, result) + assert.Equal(t, tt.expected, result) + } else { + require.NoError(t, err) + assert.NotNil(t, result) + assert.Equal(t, tt.expected, result) + } + }) + } +} + +func TestTimeToString(t *testing.T) { + tests := []struct { + name string + input *metav1.Time + expected string + }{ + { + name: "valid time", + input: &metav1.Time{Time: time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)}, + expected: "20250101120000UTC", + }, + { + name: "invalid month", + input: &metav1.Time{Time: time.Date(2025, 13, 1, 12, 0, 0, 0, time.UTC)}, + expected: "20260101120000UTC", + }, + { + name: "invalid day", + input: &metav1.Time{Time: time.Date(2025, 1, 32, 12, 0, 0, 0, time.UTC)}, + expected: "20250201120000UTC", + }, + { + name: "invalid hour", + input: &metav1.Time{Time: time.Date(2025, 1, 1, 25, 0, 0, 0, time.UTC)}, + expected: "20250102010000UTC", + }, + { + name: "invalid minutes", + input: &metav1.Time{Time: time.Date(2025, 1, 1, 12, 61, 0, 0, time.UTC)}, + expected: "20250101130100UTC", + }, + { + name: "invalid seconds", + input: &metav1.Time{Time: time.Date(2025, 1, 1, 12, 0, 61, 0, time.UTC)}, + expected: "20250101120101UTC", + }, + { + name: "midnight", + input: &metav1.Time{Time: time.Date(2025, 12, 1, 0, 0, 0, 0, time.UTC)}, + expected: "20251201000000UTC", + }, + { + name: "end of day", + input: &metav1.Time{Time: time.Date(2025, 1, 1, 23, 59, 59, 0, time.UTC)}, + expected: "20250101235959UTC", + }, + { + name: "nil time pointer", + input: nil, // Should return a zero time string + expected: "00010101000000UTC", + }, + { + name: "zero time", + input: &metav1.Time{Time: time.Time{}}, // Same as nil case + expected: "00010101000000UTC", + }, + { + name: "time with different timezone", + input: &metav1.Time{Time: time.Date(2025, 6, 15, 14, 30, 45, 0, time.FixedZone("EST", -5*60*60))}, + expected: "20250615193045UTC", // Should be converted to UTC + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := TimeToString(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestTimeToStringAndBack(t *testing.T) { + originalTime := &metav1.Time{Time: time.Date(2025, 1, 1, 12, 30, 0, 0, time.UTC)} + + timeString := TimeToString(originalTime) + parsedTime, err := StringToTime(timeString) + + require.NoError(t, err) + assert.True(t, originalTime.Time.Equal(parsedTime.Time)) +} + +func TestStringToTimeAndBack(t *testing.T) { + originalString := "20250101123000UTC" + + parsedTime, err := StringToTime(originalString) + require.NoError(t, err) + + timeString := TimeToString(parsedTime) + assert.Equal(t, originalString, timeString) +} diff --git a/pkg/capture/provider/network_capture_unix.go b/pkg/capture/provider/network_capture_unix.go index c6b966713d..04081fba53 100644 --- a/pkg/capture/provider/network_capture_unix.go +++ b/pkg/capture/provider/network_capture_unix.go @@ -111,7 +111,7 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil defer cancel() filename := file.CaptureFilename{CaptureName: ncp.CaptureName, NodeHostname: ncp.NodeHostName, StartTimestamp: ncp.StartTimestamp} - captureFileName := fmt.Sprintf("%s.pcap", filename) + captureFileName := filename.String() + ".pcap" captureFilePath := filepath.Join(ncp.TmpCaptureDir, captureFileName) // Remove the folder in case it already exists to mislead the file size check. From bceac9c968c1ad96e075f4eea9e9119e6844c349 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 28 Jul 2025 11:32:47 -0400 Subject: [PATCH 099/448] chore(deps): migrate to golangci-lint v2 (#1494) # Description As title ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Quang Nguyen --- .github/workflows/golangci-lint.yaml | 2 +- .golangci.yaml | 136 ++++++++++++++++++--------- 2 files changed, 92 insertions(+), 46 deletions(-) diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index adad41005d..2da5823fbe 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -30,7 +30,7 @@ jobs: go-version-file: go.mod - name: golangci-lint if: env.IS_NOT_MERGE_GROUP - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v8 with: version: latest args: --concurrency 4 --verbose --config=.golangci.yaml --timeout=25m diff --git a/.golangci.yaml b/.golangci.yaml index ea6e2cf9f0..eeb577c46a 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,49 +1,95 @@ +version: "2" +linters: + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - copyloopvar + - durationcheck + - err113 + - errchkjson + - errorlint + - exhaustive + - fatcontext + - gocheckcompilerdirectives + - gochecksumtype + - goconst + - gocritic + - gocyclo + - goprintffuncname + - gosec + - gosmopolitan + - lll + - loggercheck + - makezero + - misspell + - musttag + - nakedret + - nilerr + - nilnesserr + - noctx + - perfsprint + - prealloc + - promlinter + - protogetter + - reassign + - recvcheck + - revive + - rowserrcheck + - spancheck + - sqlclosecheck + - testifylint + - unparam + - wrapcheck + - zerologlint + settings: + gocritic: + disabled-checks: + - hugeParam + enabled-tags: + - diagnostic + - style + - performance + govet: + enable: + - shadow + lll: + line-length: 200 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + # some type names are caps/underscore to map OS primitive types + - linters: + - revive + - var-naming + path: pkg/metrics/types_windows.go + - linters: + - revive + - var-naming + path: pkg/metrics/types_linux.go + paths: + - third_party$ + - builtin$ + - examples$ issues: - max-same-issues: 0 max-issues-per-linter: 0 + max-same-issues: 0 new-from-rev: origin/main - exclude-rules: - # some type names are caps/underscore to map OS primitive types - - path: pkg/metrics/types_windows.go - linters: - - revive - - var-naming - - path: pkg/metrics/types_linux.go - linters: - - revive - - var-naming -linters: - presets: - - bugs - - error - - format - - performance - - unused - disable: - - gci +formatters: enable: - - copyloopvar - - goconst - - gocritic - - gocyclo - - gofmt - - goprintffuncname - - gosimple - - lll - - misspell - - nakedret - - promlinter - - revive -linters-settings: - gocritic: - enabled-tags: - - "diagnostic" - - "style" - - "performance" - disabled-checks: - - "hugeParam" - govet: - enable: - - shadow - lll: - line-length: 200 + - gofmt + - gofumpt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ From 92579b235c2818e148c9641743cf69903f280f9a Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 28 Jul 2025 14:29:13 -0400 Subject: [PATCH 100/448] fix: node watcher should only reconcile on important events (#1522) # Description Add predicates to filter out node events that are not important for Retina agent. ## Related Issue Fixed https://github.com/microsoft/retina/issues/1453 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- .../daemon/nodereconciler/cell_linux.go | 3 +- .../nodereconciler/node_controller_linux.go | 72 ++++++++++++++----- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/pkg/controllers/daemon/nodereconciler/cell_linux.go b/pkg/controllers/daemon/nodereconciler/cell_linux.go index c2f97b5dbb..b7fd1f47ef 100644 --- a/pkg/controllers/daemon/nodereconciler/cell_linux.go +++ b/pkg/controllers/daemon/nodereconciler/cell_linux.go @@ -34,7 +34,6 @@ type params struct { cell.In Config config.RetinaHubbleConfig - Logger logrus.FieldLogger Client client.Client IPCache *ipcache.IPCache } @@ -51,7 +50,7 @@ func newNodeController(params params) (*NodeReconciler, error) { n := &NodeReconciler{ Client: params.Client, clusterName: params.Config.ClusterName, - l: params.Logger.WithField("component", "node-controller"), + l: log.Logger().Named("node-controller"), nodes: make(map[string]types.Node), handlers: make(map[string]datapath.NodeHandler), c: params.IPCache, diff --git a/pkg/controllers/daemon/nodereconciler/node_controller_linux.go b/pkg/controllers/daemon/nodereconciler/node_controller_linux.go index cd67c8469d..70df453010 100644 --- a/pkg/controllers/daemon/nodereconciler/node_controller_linux.go +++ b/pkg/controllers/daemon/nodereconciler/node_controller_linux.go @@ -11,12 +11,14 @@ import ( "sync" "github.com/microsoft/retina/pkg/common/apiretry" - "github.com/sirupsen/logrus" + "github.com/microsoft/retina/pkg/log" "go.uber.org/zap" corev1 "k8s.io/api/core/v1" errors "k8s.io/apimachinery/pkg/api/errors" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/predicate" cmtypes "github.com/cilium/cilium/pkg/clustermesh/types" datapath "github.com/cilium/cilium/pkg/datapath/types" @@ -35,7 +37,7 @@ type NodeReconciler struct { clusterName string - l logrus.FieldLogger + l *log.ZapLogger handlers map[string]datapath.NodeHandler nodes map[string]types.Node c *ipc.IPCache @@ -43,20 +45,6 @@ type NodeReconciler struct { m sync.RWMutex } -// isNodeUpdated checks if the node has been updated. -// This is a simple check for labels and annotations -// being updated. Those are the only fields that are mutable. -// AKS specific for now. -func isNodeUpdated(n1, n2 types.Node) bool { - if !reflect.DeepEqual(n1.Labels, n2.Labels) { - return true - } - if !reflect.DeepEqual(n1.Annotations, n2.Annotations) { - return true - } - return false -} - func (r *NodeReconciler) addNode(node *corev1.Node) { r.m.Lock() defer r.m.Unlock() @@ -89,7 +77,7 @@ func (r *NodeReconciler) addNode(node *corev1.Node) { nd.Cluster = r.clusterName // Check if the node already exists. - if curNode, ok := r.nodes[node.Name]; ok && !isNodeUpdated(curNode, nd) { + if _, ok := r.nodes[node.Name]; ok { r.l.Debug("Node already exists", zap.String("Node", node.Name)) } @@ -117,7 +105,7 @@ func (r *NodeReconciler) addNode(node *corev1.Node) { r.l.Debug("Added IP to ipcache", zap.String("IP", address.ToString())) } - r.l.Info("Added Node", zap.String("Node", node.Name)) + r.l.Info("Added Node", zap.String("name", nd.Name)) } func (r *NodeReconciler) deleteNode(node *corev1.Node) { @@ -204,8 +192,45 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. // SetupWithManager sets up the controller with the Manager. func (r *NodeReconciler) SetupWithManager(mgr ctrl.Manager) error { r.l.Debug("Setting up Node controller") + + // Create a predicate to filter node events + nodePredicate := predicate.Funcs{ + CreateFunc: func(event.CreateEvent) bool { + // Always reconcile on node creation + return true + }, + DeleteFunc: func(event.DeleteEvent) bool { + // Always reconcile on node deletion + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + oldNode, ok := e.ObjectOld.(*corev1.Node) + if !ok { + r.l.Error("Failed to convert old object to Node") + return false + } + + newNode, ok := e.ObjectNew.(*corev1.Node) + if !ok { + r.l.Error("Failed to convert new object to Node") + return false + } + + // Compare node IP addresses + oldIPs := extractNodeIPs(oldNode) + newIPs := extractNodeIPs(newNode) + + // Only reconcile if IPs changed or labels/annotations changed + return !reflect.DeepEqual(oldIPs, newIPs) || !reflect.DeepEqual(oldNode.Labels, newNode.Labels) || !reflect.DeepEqual(oldNode.Annotations, newNode.Annotations) + }, + GenericFunc: func(event.GenericEvent) bool { + return false + }, + } + err := ctrl.NewControllerManagedBy(mgr). For(&corev1.Node{}). + WithEventFilter(nodePredicate). Complete(r) if err != nil { return fmt.Errorf("setting up node controller: %w", err) @@ -244,3 +269,14 @@ func (r *NodeReconciler) StartNeighborRefresh(datapath.NodeNeighbors) {} func (r *NodeReconciler) StartNodeNeighborLinkUpdater(datapath.NodeNeighbors) {} func (r *NodeReconciler) SetPrefixClusterMutatorFn(func(*types.Node) []cmtypes.PrefixClusterOpts) {} + +// extractNodeIPs extracts IP addresses from a node +func extractNodeIPs(node *corev1.Node) map[string]string { + ips := make(map[string]string) + for _, addr := range node.Status.Addresses { + if addr.Type == corev1.NodeInternalIP || addr.Type == corev1.NodeExternalIP { + ips[string(addr.Type)] = addr.Address + } + } + return ips +} From 5d0adc1d24f83c89b803f06b33b00fd0d767c01c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:10:20 -0400 Subject: [PATCH 101/448] deps: bump github.com/aws/aws-sdk-go-v2 from 1.36.6 to 1.37.0 (#1780) Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.36.6 to 1.37.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2&package-manager=go_modules&previous-version=1.36.6&new-version=1.37.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 33b2f98689..350ac0bb1a 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect - github.com/aws/smithy-go v1.22.4 // indirect + github.com/aws/smithy-go v1.22.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -272,7 +272,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.36.6 + github.com/aws/aws-sdk-go-v2 v1.37.0 github.com/aws/aws-sdk-go-v2/config v1.29.18 github.com/aws/aws-sdk-go-v2/credentials v1.17.71 github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 diff --git a/go.sum b/go.sum index e14bbd8742..db37b27fb7 100644 --- a/go.sum +++ b/go.sum @@ -240,8 +240,8 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU= -github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2 v1.37.0 h1:YtCOESR/pN4j5oA7cVHSfOwIcuh/KwHC4DOSXFbv5F0= +github.com/aws/aws-sdk-go-v2 v1.37.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= @@ -282,8 +282,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWd github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= -github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= -github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= +github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f/go.mod h1:rAE739ssmE5O5fLuQ2y8uHdmOJaelE5I0Es3SxV0y1A= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From 5b8e54d50ebd41cc401b72ee5e79853be94c1a82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 13:51:56 -0400 Subject: [PATCH 102/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.29.18 to 1.30.0 (#1778) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.29.18 to 1.30.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.29.18&new-version=1.30.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 20 ++++++++++---------- go.sum | 40 ++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 350ac0bb1a..e7761b4949 100644 --- a/go.mod +++ b/go.mod @@ -47,18 +47,18 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.26.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.35.0 // indirect github.com/aws/smithy-go v1.22.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 @@ -273,8 +273,8 @@ require ( github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.37.0 - github.com/aws/aws-sdk-go-v2/config v1.29.18 - github.com/aws/aws-sdk-go-v2/credentials v1.17.71 + github.com/aws/aws-sdk-go-v2/config v1.30.0 + github.com/aws/aws-sdk-go-v2/credentials v1.18.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 diff --git a/go.sum b/go.sum index db37b27fb7..4b554405aa 100644 --- a/go.sum +++ b/go.sum @@ -244,18 +244,18 @@ github.com/aws/aws-sdk-go-v2 v1.37.0 h1:YtCOESR/pN4j5oA7cVHSfOwIcuh/KwHC4DOSXFbv github.com/aws/aws-sdk-go-v2 v1.37.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= -github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= -github.com/aws/aws-sdk-go-v2/config v1.29.18/go.mod h1:bvz8oXugIsH8K7HLhBv06vDqnFv3NsGDt2Znpk7zmOU= -github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= -github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33/go.mod h1:caS/m4DI+cij2paz3rtProRBI4s/+TCiWoaWZuQ9010= +github.com/aws/aws-sdk-go-v2/config v1.30.0 h1:XhzXYU2x/T441/0CBh0g6UUC/OFGk+FRpl3ThI8AqM8= +github.com/aws/aws-sdk-go-v2/config v1.30.0/go.mod h1:4j78A2ko2xc7SMLjjSUrgpp42vyneH9c8j3emf/CLTo= +github.com/aws/aws-sdk-go-v2/credentials v1.18.0 h1:r9W/BX4B1dEbsd2NogyuFXmEfYhdUULUVEOh0SDAovw= +github.com/aws/aws-sdk-go-v2/credentials v1.18.0/go.mod h1:SMtUJQRWEpyfC+ouDJNYdI7NNMqUjHM/Oaf0FV+vWNs= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0 h1:ouCRc4lCriJtCnrIN4Kw2tA/uETRZBrxwb/607gRvkE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0/go.mod h1:LW9/PxQD1SYFC7pnWcgqPhoyZprhjEdg5hBK6qYPLW8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0 h1:H2iZoqW/v2Jnrh1FnU725Bq6KJ0k2uP63yH+DcY+HUI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0/go.mod h1:L0FqLbwMXHvNC/7crWV1iIxUlOKYZUE8KuTIA+TozAI= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0 h1:EDped/rNzAhFPhVY0sDGbtD16OKqksfA8OjF/kLEgw8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0/go.mod h1:uUI335jvzpZRPpjYx6ODc/wg1qH+NnoSTK/FwVeK0C0= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics= @@ -264,24 +264,24 @@ github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7H github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0 h1:eRhU3Sh8dGbaniI6B+I48XJMrTPRkK4DKo+vqIxziOU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0/go.mod h1:paNLV18DZ6FnWE/bd06RIKPDIFpjuvCkGKWTG/GDBeM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 h1:rGtWqkQbPk7Bkwuv3NzpE/scwwL9sC1Ul3tn9x83DUI= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.6/go.mod h1:u4ku9OLv4TO4bCPdxf4fA1upaMaJmP9ZijGk3AAOC6Q= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWdumLxNbzz1P0zJoezkJc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= -github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= -github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= +github.com/aws/aws-sdk-go-v2/service/sso v1.26.0 h1:cuFWHH87GP1NBGXXfMicUbE7Oty5KpPxN6w4JpmuxYc= +github.com/aws/aws-sdk-go-v2/service/sso v1.26.0/go.mod h1:aJBemdlbCKyOXEXdXBqS7E+8S9XTDcOTaoOjtng54hA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0 h1:t2va+wewPOYIqC6XyJ4MGjiGKkczMAPsgq5W4FtL9ME= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0/go.mod h1:ExCTcqYqN0hYYRsDlBVU8+68grqlWdgX9/nZJwQW4aY= +github.com/aws/aws-sdk-go-v2/service/sts v1.35.0 h1:FD9agdG4CeOGS3ORLByJk56YIXDS7mxFpmZyCtpqExc= +github.com/aws/aws-sdk-go-v2/service/sts v1.35.0/go.mod h1:NDzDPbBF1xtSTZUMuZx0w3hIfWzcL7X2AQ0Tr9becIQ= github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= From ba674a3668d6c9dea55a025043d856e33b2a5dca Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Wed, 30 Jul 2025 13:50:56 +0100 Subject: [PATCH 103/448] fix: fix zap.Any logging issues causing unsupported value type errors (#1783) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The `zap.Any` logger was being used with complex objects in the latency metrics module, resulting in uninformative "unsupported value type" error messages that made debugging difficult: ``` ts=2025-06-12T14:49:33.339Z level=debug caller=metrics/latency.go:126 msg="Evicted item" item= itemError="unsupported value type" ts=2025-06-12T14:43:38.295Z level=debug caller=metrics/latency.go:129 msg="Incremented no response metric" metric= metricError="unsupported value type" ``` ## Solution Replaced `zap.Any` calls with appropriate structured logging using specific zap field types: ### Before (problematic): ```go lm.l.Debug("Evicted item", zap.Any("item", item)) lm.l.Debug("Incremented no response metric", zap.Any("metric", lm.noResponseMetric)) lm.l.Debug("Add apiserver ips", zap.Any("ips", apiServerIPs)) ``` ### After (fixed): ```go k := item.Key() v := item.Value() lm.l.Debug("Evicted item", zap.String("srcIP", k.srcIP), zap.String("dstIP", k.dstIP), zap.Uint32("srcPort", k.srcP), zap.Uint32("dstPort", k.dstP), zap.Uint64("id", k.id), zap.Int32("timestamp", v.t)) lm.l.Debug("Incremented no response metric", zap.String("metric", "adv_node_apiserver_no_response")) ipStrings := make([]string, len(apiServerIPs)) for i, ip := range apiServerIPs { ipStrings[i] = ip.String() } lm.l.Debug("Add apiserver ips", zap.Strings("ips", ipStrings)) ``` ### Logs before and after: ```` ts=2025-06-12T14:49:33.339Z level=debug caller=metrics/latency.go:126 msg="Evicted item" item= itemError="unsupported value type" ts=2025-06-12T14:43:38.295Z level=debug caller=metrics/latency.go:129 msg="Incremented no response metric" metric= metricError="unsupported value type" ```` ``` ts=2025-07-23T16:20:50.047Z level=debug caller=metrics/latency.go:128 msg="Evicted item" srcIP=10.224.0.4 dstIP=20.13.226.96 srcPort=56272 dstPort=443 id=614403966 timestamp=543825424 ts=2025-07-23T16:20:50.047Z level=debug caller=metrics/latency.go:137 msg="Incremented no response metric" metric=adv_node_apiserver_no_response ``` ## Benefits - **Informative logging**: Debug messages now show actual values instead of "unsupported value type" - **Better debugging**: Network connection details (IPs, ports, timestamps) are clearly visible - **Structured data**: Proper field names make log parsing and analysis easier - **No breaking changes**: Only affects debug log output format ## Testing - All existing tests pass (23/23) - No "unsupported value type" errors from latency.go in test output - Verified structured logging produces readable output with meaningful field names Fixes #1680. --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Signed-off-by: Iti Agrawal --- pkg/module/metrics/latency.go | 42 ++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/pkg/module/metrics/latency.go b/pkg/module/metrics/latency.go index 3810054d04..ee14c9dbd2 100644 --- a/pkg/module/metrics/latency.go +++ b/pkg/module/metrics/latency.go @@ -123,10 +123,18 @@ func (lm *LatencyMetrics) Init(metricName string) { lm.cache.OnEviction(func(ctx context.Context, reason ttlcache.EvictionReason, item *ttlcache.Item[key, *val]) { if reason == ttlcache.EvictionReasonExpired { // Didn't get the corresponding packet. - lm.l.Debug("Evicted item", zap.Any("item", item)) + k := item.Key() + v := item.Value() + lm.l.Debug("Evicted item", + zap.String("srcIP", k.srcIP), + zap.String("dstIP", k.dstIP), + zap.Uint32("srcPort", k.srcP), + zap.Uint32("dstPort", k.dstP), + zap.Uint64("id", k.id), + zap.Int32("timestamp", v.t)) if lm.noResponseMetric != nil { lm.noResponseMetric.WithLabelValues("no_response").Inc() - lm.l.Debug("Incremented no response metric", zap.Any("metric", lm.noResponseMetric)) + lm.l.Debug("Incremented no response metric", zap.String("metric", noResponseFromNodeAPIServerName)) } } }) @@ -323,25 +331,33 @@ func (lm *LatencyMetrics) apiserverWatcherCallbackFn(obj interface{}) { switch event.Type { case cc.EventTypeAddAPIServerIPs: - lm.l.Debug("Add apiserver ips", zap.Any("ips", apiServerIPs)) - lm.addIps(apiServerIPs) + ipStrings := lm.addIps(apiServerIPs) + lm.l.Debug("Add apiserver ips", zap.Strings("ips", ipStrings)) case cc.EventTypeDeleteAPIServerIPs: - lm.l.Debug("Delete apiserver ips", zap.Any("ips", apiServerIPs)) - lm.removeIps(apiServerIPs) + ipStrings := lm.removeIps(apiServerIPs) + lm.l.Debug("Delete apiserver ips", zap.Strings("ips", ipStrings)) default: - lm.l.Debug("Unknown event type", zap.Any("event", event)) + lm.l.Debug("Unknown event type", zap.String("eventType", event.Type.String())) } } -func (lm *LatencyMetrics) addIps(ips []net.IP) { - for _, ip := range ips { - lm.apiServerIps[ip.String()] = struct{}{} +func (lm *LatencyMetrics) addIps(ips []net.IP) []string { + ipStrings := make([]string, len(ips)) + for i, ip := range ips { + ipString := ip.String() + ipStrings[i] = ipString + lm.apiServerIps[ipString] = struct{}{} } + return ipStrings } -func (lm *LatencyMetrics) removeIps(ips []net.IP) { - for _, ip := range ips { - delete(lm.apiServerIps, ip.String()) +func (lm *LatencyMetrics) removeIps(ips []net.IP) []string { + ipStrings := make([]string, len(ips)) + for i, ip := range ips { + ipString := ip.String() + ipStrings[i] = ipString + delete(lm.apiServerIps, ipString) } + return ipStrings } From 03b7543290d4cc108c28b75f94be6b66221b1098 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Wed, 30 Jul 2025 11:51:34 -0700 Subject: [PATCH 104/448] chore: add eventwriter dispatch workflow (#1789) # Description Add base workflow file to establish permissions for workflow on default branch, issue here: https://github.com/microsoft/retina/actions/runs/16605350739/job/47054435987#step:11:41 --- .github/workflows/e2e-test-event-writer.yml | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/e2e-test-event-writer.yml diff --git a/.github/workflows/e2e-test-event-writer.yml b/.github/workflows/e2e-test-event-writer.yml new file mode 100644 index 0000000000..bd41d73b99 --- /dev/null +++ b/.github/workflows/e2e-test-event-writer.yml @@ -0,0 +1,34 @@ +name: Build E2E Test Event Writer +on: + push: + branches: + - main + - dev/** + merge_group: + types: [checks_requested] + workflow_dispatch: + +permissions: + contents: read + id-token: write + packages: write + +env: + EVENT_WRITER_PATH: "${{ github.workspace }}/test/e2e/tools/event-writer/" + +jobs: + retina-win-e2e-bpf-images: + name: Build E2E Test Event Writer + runs-on: windows-2022 + + env: + IS_MERGE_GROUP: ${{ (github.event_name == 'merge_group') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/dev/v0.0.33-windows' && github.repository == 'microsoft/retina') }} + + strategy: + matrix: + platform: ["windows"] + arch: ["amd64"] + + steps: + - name: Checkout code + uses: actions/checkout@v4.2.2 From f660cab7c477489cb08860d4acaf46f45d8eaf77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 16:04:13 -0400 Subject: [PATCH 105/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.84.1 to 1.85.0 (#1786) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.84.1 to 1.85.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.84.1&new-version=1.85.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index e7761b4949..2c5cc6efb3 100644 --- a/go.mod +++ b/go.mod @@ -46,16 +46,16 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.26.0 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.35.0 // indirect @@ -275,7 +275,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.37.0 github.com/aws/aws-sdk-go-v2/config v1.30.0 github.com/aws/aws-sdk-go-v2/credentials v1.18.0 - github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 + github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 4b554405aa..e8183de543 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,8 @@ github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.37.0 h1:YtCOESR/pN4j5oA7cVHSfOwIcuh/KwHC4DOSXFbv5F0= github.com/aws/aws-sdk-go-v2 v1.37.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= github.com/aws/aws-sdk-go-v2/config v1.30.0 h1:XhzXYU2x/T441/0CBh0g6UUC/OFGk+FRpl3ThI8AqM8= github.com/aws/aws-sdk-go-v2/config v1.30.0/go.mod h1:4j78A2ko2xc7SMLjjSUrgpp42vyneH9c8j3emf/CLTo= github.com/aws/aws-sdk-go-v2/credentials v1.18.0 h1:r9W/BX4B1dEbsd2NogyuFXmEfYhdUULUVEOh0SDAovw= @@ -258,24 +258,24 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0 h1:EDped/rNzAhFPhVY0sD github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0/go.mod h1:uUI335jvzpZRPpjYx6ODc/wg1qH+NnoSTK/FwVeK0C0= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37/go.mod h1:Pi6ksbniAWVwu2S8pEzcYPyhUkAcLaufxN7PfAUQjBk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0 h1:iLvW/zOkHGU3BDU5thWnj+UZ9pjhuVhv1loLj7yVtBw= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0/go.mod h1:Fn3gvhdF1x5Rs9nUoCy/fJT1ms8f8dO7RqM9lJHuazQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0 h1:qGyLBQPphYzUf+IIlb5tHnvg1U2Vc5hXPcP7oRSQfy0= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0/go.mod h1:g+dzKSLXiR/8ATkPXmLhPOI6rDdjLP3tngeo3FvDcIw= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0 h1:eRhU3Sh8dGbaniI6B+I48XJMrTPRkK4DKo+vqIxziOU= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0/go.mod h1:paNLV18DZ6FnWE/bd06RIKPDIFpjuvCkGKWTG/GDBeM= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0 h1:6jusT+XCcvnD+Elxvm7bUf5sCMTpZEp3AKjYQ4tWJSo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0/go.mod h1:LimGpdIF/sTBdgqwOEkrArXLCoTamK/9L9x8IKBFTIc= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= +github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 h1:gAV4NEp4A+JOrIdoXkAeyy6IOo7+X2s/jRuaHKYiMaU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0/go.mod h1:JIQwK8sZ5MuKGm5rrFwp9MHUcyYEsQNpVixuPDlnwaU= github.com/aws/aws-sdk-go-v2/service/sso v1.26.0 h1:cuFWHH87GP1NBGXXfMicUbE7Oty5KpPxN6w4JpmuxYc= github.com/aws/aws-sdk-go-v2/service/sso v1.26.0/go.mod h1:aJBemdlbCKyOXEXdXBqS7E+8S9XTDcOTaoOjtng54hA= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0 h1:t2va+wewPOYIqC6XyJ4MGjiGKkczMAPsgq5W4FtL9ME= From 44c9e5490782688634fe9f41ea2c4473f5579c01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:45:12 -0400 Subject: [PATCH 106/448] deps: bump github.com/aws/aws-sdk-go-v2/credentials from 1.18.0 to 1.18.1 (#1787) Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.18.0 to 1.18.1.
Changelog

Sourced from github.com/aws/aws-sdk-go-v2/credentials's changelog.

Release (2023-06-13)

General Highlights

  • Dependency Update: Updated to the latest SDK module versions

Module Highlights

  • github.com/aws/aws-sdk-go-v2/service/cloudtrail: v1.27.0
    • Feature: This feature allows users to view dashboards for CloudTrail Lake event data stores.
  • github.com/aws/aws-sdk-go-v2/service/codegurusecurity: v1.0.0
    • Release: New AWS service client module
    • Feature: Initial release of Amazon CodeGuru Security APIs
  • github.com/aws/aws-sdk-go-v2/service/drs: v1.14.0
    • Feature: Added APIs to support network replication and recovery using AWS Elastic Disaster Recovery.
  • github.com/aws/aws-sdk-go-v2/service/ec2: v1.100.0
    • Feature: This release introduces a new feature, EC2 Instance Connect Endpoint, that enables you to connect to a resource over TCP, without requiring the resource to have a public IPv4 address.
  • github.com/aws/aws-sdk-go-v2/service/imagebuilder: v1.23.5
    • Documentation: Change the Image Builder ImagePipeline dateNextRun field to more accurately describe the data.
  • github.com/aws/aws-sdk-go-v2/service/lightsail: v1.27.0
    • Feature: This release adds pagination for the Get Certificates API operation.
  • github.com/aws/aws-sdk-go-v2/service/s3: v1.34.0
    • Feature: Integrate double encryption feature to SDKs.
    • Bug Fix: Fix HeadObject to return types.Nound when an object does not exist. Fixes 2084
  • github.com/aws/aws-sdk-go-v2/service/securityhub: v1.33.0
    • Feature: Add support for Security Hub Automation Rules
  • github.com/aws/aws-sdk-go-v2/service/simspaceweaver: v1.3.0
    • Feature: This release fixes using aws-us-gov ARNs in API calls and adds documentation for snapshot APIs.
  • github.com/aws/aws-sdk-go-v2/service/verifiedpermissions: v1.0.0
    • Release: New AWS service client module
    • Feature: GA release of Amazon Verified Permissions.
  • github.com/aws/aws-sdk-go-v2/service/wafv2: v1.35.0
    • Feature: You can now detect and block fraudulent account creation attempts with the new AWS WAF Fraud Control account creation fraud prevention (ACFP) managed rule group AWSManagedRulesACFPRuleSet.
  • github.com/aws/aws-sdk-go-v2/service/wellarchitected: v1.21.0
    • Feature: AWS Well-Architected now supports Profiles that help customers prioritize which questions to focus on first by providing a list of prioritized questions that are better aligned with their business goals and outcomes.

Release (2023-06-12)

General Highlights

  • Dependency Update: Updated to the latest SDK module versions

Module Highlights

  • github.com/aws/aws-sdk-go-v2/service/amplifyuibuilder: v1.11.0
    • Feature: AWS Amplify UIBuilder is launching Codegen UI, a new feature that enables you to generate your amplify uibuilder components and forms.
  • github.com/aws/aws-sdk-go-v2/service/dynamodb: v1.19.8
    • Documentation: Documentation updates for DynamoDB
  • github.com/aws/aws-sdk-go-v2/service/dynamodbstreams: v1.14.12
    • Documentation: Documentation updates for DynamoDB Streams
  • github.com/aws/aws-sdk-go-v2/service/fsx: v1.29.0
    • Feature: Amazon FSx for NetApp ONTAP now supports joining a storage virtual machine (SVM) to Active Directory after the SVM has been created.
  • github.com/aws/aws-sdk-go-v2/service/opensearch: v1.18.0
    • Feature: This release adds support for SkipUnavailable connection property for cross cluster search

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/credentials&package-manager=go_modules&previous-version=1.18.0&new-version=1.18.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 2c5cc6efb3..776555db6a 100644 --- a/go.mod +++ b/go.mod @@ -47,18 +47,18 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.26.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.35.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.35.1 // indirect github.com/aws/smithy-go v1.22.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 @@ -272,9 +272,9 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.37.0 + github.com/aws/aws-sdk-go-v2 v1.37.1 github.com/aws/aws-sdk-go-v2/config v1.30.0 - github.com/aws/aws-sdk-go-v2/credentials v1.18.0 + github.com/aws/aws-sdk-go-v2/credentials v1.18.2 github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 diff --git a/go.sum b/go.sum index e8183de543..9c2413d2bf 100644 --- a/go.sum +++ b/go.sum @@ -240,22 +240,22 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.37.0 h1:YtCOESR/pN4j5oA7cVHSfOwIcuh/KwHC4DOSXFbv5F0= -github.com/aws/aws-sdk-go-v2 v1.37.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= +github.com/aws/aws-sdk-go-v2 v1.37.1 h1:SMUxeNz3Z6nqGsXv0JuJXc8w5YMtrQMuIBmDx//bBDY= +github.com/aws/aws-sdk-go-v2 v1.37.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= github.com/aws/aws-sdk-go-v2/config v1.30.0 h1:XhzXYU2x/T441/0CBh0g6UUC/OFGk+FRpl3ThI8AqM8= github.com/aws/aws-sdk-go-v2/config v1.30.0/go.mod h1:4j78A2ko2xc7SMLjjSUrgpp42vyneH9c8j3emf/CLTo= -github.com/aws/aws-sdk-go-v2/credentials v1.18.0 h1:r9W/BX4B1dEbsd2NogyuFXmEfYhdUULUVEOh0SDAovw= -github.com/aws/aws-sdk-go-v2/credentials v1.18.0/go.mod h1:SMtUJQRWEpyfC+ouDJNYdI7NNMqUjHM/Oaf0FV+vWNs= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0 h1:ouCRc4lCriJtCnrIN4Kw2tA/uETRZBrxwb/607gRvkE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.17.0/go.mod h1:LW9/PxQD1SYFC7pnWcgqPhoyZprhjEdg5hBK6qYPLW8= +github.com/aws/aws-sdk-go-v2/credentials v1.18.2 h1:mfm0GKY/PHLhs7KO0sUaOtFnIQ15Qqxt+wXbO/5fIfs= +github.com/aws/aws-sdk-go-v2/credentials v1.18.2/go.mod h1:v0SdJX6ayPeZFQxgXUKw5RhLpAoZUuynxWDfh8+Eknc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 h1:owmNBboeA0kHKDcdF8KiSXmrIuXZustfMGGytv6OMkM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1/go.mod h1:Bg1miN59SGxrZqlP8vJZSmXW+1N8Y1MjQDq1OfuNod8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0 h1:H2iZoqW/v2Jnrh1FnU725Bq6KJ0k2uP63yH+DcY+HUI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.0/go.mod h1:L0FqLbwMXHvNC/7crWV1iIxUlOKYZUE8KuTIA+TozAI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0 h1:EDped/rNzAhFPhVY0sDGbtD16OKqksfA8OjF/kLEgw8= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.0/go.mod h1:uUI335jvzpZRPpjYx6ODc/wg1qH+NnoSTK/FwVeK0C0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1 h1:ksZXBYv80EFTcgc8OJO48aQ8XDWXIQL7gGasPeCoTzI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1/go.mod h1:HSksQyyJETVZS7uM54cir0IgxttTD+8aEoJMPGepHBI= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1 h1:+dn/xF/05utS7tUhjIcndbuaPjfll2LhbH1cCDGLYUQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1/go.mod h1:hyAGz30LHdm5KBZDI58MXx5lDVZ5CUfvfTZvMu4HCZo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0 h1:iLvW/zOkHGU3BDU5thWnj+UZ9pjhuVhv1loLj7yVtBw= @@ -268,20 +268,20 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2J github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0 h1:qGyLBQPphYzUf+IIlb5tHnvg1U2Vc5hXPcP7oRSQfy0= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0/go.mod h1:g+dzKSLXiR/8ATkPXmLhPOI6rDdjLP3tngeo3FvDcIw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0 h1:eRhU3Sh8dGbaniI6B+I48XJMrTPRkK4DKo+vqIxziOU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.0/go.mod h1:paNLV18DZ6FnWE/bd06RIKPDIFpjuvCkGKWTG/GDBeM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 h1:ky79ysLMxhwk5rxJtS+ILd3Mc8kC5fhsLBrP27r6h4I= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1/go.mod h1:+2MmkvFvPYM1vsozBWduoLJUi5maxFk5B7KJFECujhY= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0 h1:6jusT+XCcvnD+Elxvm7bUf5sCMTpZEp3AKjYQ4tWJSo= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0/go.mod h1:LimGpdIF/sTBdgqwOEkrArXLCoTamK/9L9x8IKBFTIc= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 h1:gAV4NEp4A+JOrIdoXkAeyy6IOo7+X2s/jRuaHKYiMaU= github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0/go.mod h1:JIQwK8sZ5MuKGm5rrFwp9MHUcyYEsQNpVixuPDlnwaU= -github.com/aws/aws-sdk-go-v2/service/sso v1.26.0 h1:cuFWHH87GP1NBGXXfMicUbE7Oty5KpPxN6w4JpmuxYc= -github.com/aws/aws-sdk-go-v2/service/sso v1.26.0/go.mod h1:aJBemdlbCKyOXEXdXBqS7E+8S9XTDcOTaoOjtng54hA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0 h1:t2va+wewPOYIqC6XyJ4MGjiGKkczMAPsgq5W4FtL9ME= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.0/go.mod h1:ExCTcqYqN0hYYRsDlBVU8+68grqlWdgX9/nZJwQW4aY= -github.com/aws/aws-sdk-go-v2/service/sts v1.35.0 h1:FD9agdG4CeOGS3ORLByJk56YIXDS7mxFpmZyCtpqExc= -github.com/aws/aws-sdk-go-v2/service/sts v1.35.0/go.mod h1:NDzDPbBF1xtSTZUMuZx0w3hIfWzcL7X2AQ0Tr9becIQ= +github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 h1:uWaz3DoNK9MNhm7i6UGxqufwu3BEuJZm72WlpGwyVtY= +github.com/aws/aws-sdk-go-v2/service/sso v1.26.1/go.mod h1:ILpVNjL0BO+Z3Mm0SbEeUoYS9e0eJWV1BxNppp0fcb8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 h1:XdG6/o1/ZDmn3wJU5SRAejHaWgKS4zHv0jBamuKuS2k= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1/go.mod h1:oiotGTKadCOCl3vg/tYh4k45JlDF81Ka8rdumNhEnIQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.35.1 h1:iF4Xxkc0H9c/K2dS0zZw3SCkj0Z7n6AMnUiiyoJND+I= +github.com/aws/aws-sdk-go-v2/service/sts v1.35.1/go.mod h1:0bxIatfN0aLq4mjoLDeBpOjOke68OsFlXPDFJ7V0MYw= github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= From 4cc9163611b918605bb19fcbdae991b158fc4c1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 20:13:57 -0400 Subject: [PATCH 107/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.30.0 to 1.30.1 (#1785) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.30.0 to 1.30.1.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.30.0&new-version=1.30.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 776555db6a..a96a59a8fd 100644 --- a/go.mod +++ b/go.mod @@ -273,7 +273,7 @@ require ( github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.37.1 - github.com/aws/aws-sdk-go-v2/config v1.30.0 + github.com/aws/aws-sdk-go-v2/config v1.30.2 github.com/aws/aws-sdk-go-v2/credentials v1.18.2 github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 diff --git a/go.sum b/go.sum index 9c2413d2bf..7aeb389d2e 100644 --- a/go.sum +++ b/go.sum @@ -244,8 +244,8 @@ github.com/aws/aws-sdk-go-v2 v1.37.1 h1:SMUxeNz3Z6nqGsXv0JuJXc8w5YMtrQMuIBmDx//b github.com/aws/aws-sdk-go-v2 v1.37.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= -github.com/aws/aws-sdk-go-v2/config v1.30.0 h1:XhzXYU2x/T441/0CBh0g6UUC/OFGk+FRpl3ThI8AqM8= -github.com/aws/aws-sdk-go-v2/config v1.30.0/go.mod h1:4j78A2ko2xc7SMLjjSUrgpp42vyneH9c8j3emf/CLTo= +github.com/aws/aws-sdk-go-v2/config v1.30.2 h1:YE1BmSc4fFYqFgN1mN8uzrtc7R9x+7oSWeX8ckoltAw= +github.com/aws/aws-sdk-go-v2/config v1.30.2/go.mod h1:UNrLGZ6jfAVjgVJpkIxjLufRJqTXCVYOpkeVf83kwBo= github.com/aws/aws-sdk-go-v2/credentials v1.18.2 h1:mfm0GKY/PHLhs7KO0sUaOtFnIQ15Qqxt+wXbO/5fIfs= github.com/aws/aws-sdk-go-v2/credentials v1.18.2/go.mod h1:v0SdJX6ayPeZFQxgXUKw5RhLpAoZUuynxWDfh8+Eknc= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 h1:owmNBboeA0kHKDcdF8KiSXmrIuXZustfMGGytv6OMkM= From a1f07b370fbdb80f3ca00b28d4da9c649f682b03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 23:59:16 -0400 Subject: [PATCH 108/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.85.0 to 1.85.1 (#1793) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.85.0 to 1.85.1.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.85.0&new-version=1.85.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index a96a59a8fd..e8fd83a032 100644 --- a/go.mod +++ b/go.mod @@ -51,11 +51,11 @@ require ( github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.35.1 // indirect @@ -275,7 +275,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.37.1 github.com/aws/aws-sdk-go-v2/config v1.30.2 github.com/aws/aws-sdk-go-v2/credentials v1.18.2 - github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 7aeb389d2e..04ca5b1170 100644 --- a/go.sum +++ b/go.sum @@ -258,24 +258,24 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1 h1:+dn/xF/05utS7tUhjIc github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1/go.mod h1:hyAGz30LHdm5KBZDI58MXx5lDVZ5CUfvfTZvMu4HCZo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0 h1:iLvW/zOkHGU3BDU5thWnj+UZ9pjhuVhv1loLj7yVtBw= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.0/go.mod h1:Fn3gvhdF1x5Rs9nUoCy/fJT1ms8f8dO7RqM9lJHuazQ= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.1 h1:4HbnOGE9491a9zYJ9VpPh1ApgEq6ZlD4Kuv1PJenFpc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.1/go.mod h1:Z6QnHC6TmpJWUxAy8FI4JzA7rTwl6EIANkyK9OR5z5w= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0 h1:qGyLBQPphYzUf+IIlb5tHnvg1U2Vc5hXPcP7oRSQfy0= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.0/go.mod h1:g+dzKSLXiR/8ATkPXmLhPOI6rDdjLP3tngeo3FvDcIw= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1 h1:ps3nrmBWdWwakZBydGX1CxeYFK80HsQ79JLMwm7Y4/c= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1/go.mod h1:bAdfrfxENre68Hh2swNaGEVuFYE74o0SaSCAlaG9E74= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 h1:ky79ysLMxhwk5rxJtS+ILd3Mc8kC5fhsLBrP27r6h4I= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1/go.mod h1:+2MmkvFvPYM1vsozBWduoLJUi5maxFk5B7KJFECujhY= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0 h1:6jusT+XCcvnD+Elxvm7bUf5sCMTpZEp3AKjYQ4tWJSo= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.0/go.mod h1:LimGpdIF/sTBdgqwOEkrArXLCoTamK/9L9x8IKBFTIc= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1 h1:MdVYlN5pcQu1t1OYx4Ajo3fKl1IEhzgdPQbYFCRjYS8= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1/go.mod h1:iikmNLrvHm2p4a3/4BPeix2S9P+nW8yM1IZW73x8bFA= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0 h1:gAV4NEp4A+JOrIdoXkAeyy6IOo7+X2s/jRuaHKYiMaU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.85.0/go.mod h1:JIQwK8sZ5MuKGm5rrFwp9MHUcyYEsQNpVixuPDlnwaU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1 h1:Hsqo8+dFxSdDvv9B2PgIx1AJAnDpqgS0znVI+R+MoGY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1/go.mod h1:8Q0TAPXD68Z8YqlcIGHs/UNIDHsxErV9H4dl4vJEpgw= github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 h1:uWaz3DoNK9MNhm7i6UGxqufwu3BEuJZm72WlpGwyVtY= github.com/aws/aws-sdk-go-v2/service/sso v1.26.1/go.mod h1:ILpVNjL0BO+Z3Mm0SbEeUoYS9e0eJWV1BxNppp0fcb8= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 h1:XdG6/o1/ZDmn3wJU5SRAejHaWgKS4zHv0jBamuKuS2k= From 5511e0b47701c8898acd36df775180e4be302398 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 00:17:29 -0400 Subject: [PATCH 109/448] deps: bump github.com/prometheus/client_golang from 1.22.0 to 1.23.0 (#1792) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.22.0 to 1.23.0.
Release notes

Sourced from github.com/prometheus/client_golang's releases.

v1.23.0 - 2025-07-30

  • [CHANGE] Minimum required Go version is now 1.23, only the two latest Go versions are supported from now on. #1812
  • [FEATURE] Add WrapCollectorWith and WrapCollectorWithPrefix #1766
  • [FEATURE] Add exemplars for native histograms #1686
  • [ENHANCEMENT] exp/api: Bubble up status code from writeResponse #1823
  • [ENHANCEMENT] collector/go: Update runtime metrics for Go v1.23 and v1.24 #1833
  • [BUGFIX] exp/api: client prompt return on context cancellation #1729

... (truncated)

Changelog

Sourced from github.com/prometheus/client_golang's changelog.

1.23.0 / 2025-07-30

  • [CHANGE] Minimum required Go version is now 1.23, only the two latest Go versions are supported from now on. #1812
  • [FEATURE] Add WrapCollectorWith and WrapCollectorWithPrefix #1766
  • [FEATURE] Add exemplars for native histograms #1686
  • [ENHANCEMENT] exp/api: Bubble up status code from writeResponse #1823
  • [ENHANCEMENT] collector/go: Update runtime metrics for Go v1.23 and v1.24 #1833
  • [BUGFIX] exp/api: client prompt return on context cancellation #1729
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/client_golang&package-manager=go_modules&previous-version=1.22.0&new-version=1.23.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e8fd83a032..9af56dd2f1 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24.3 require ( github.com/go-chi/chi/v5 v5.2.2 github.com/google/uuid v1.6.0 - github.com/prometheus/client_golang v1.22.0 + github.com/prometheus/client_golang v1.23.0 github.com/spf13/cobra v1.9.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 @@ -178,7 +178,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/procfs v0.16.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/rubenv/sql-migrate v1.7.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a // indirect diff --git a/go.sum b/go.sum index 04ca5b1170..714053d3bb 100644 --- a/go.sum +++ b/go.sum @@ -1247,8 +1247,8 @@ github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= +github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1261,8 +1261,8 @@ github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGI github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= -github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= From a24a3bae52b8a7e70c010b9c08390e16a5388839 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 14:29:11 -0400 Subject: [PATCH 110/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.18.1 to 1.18.2 (#1795) Bumps [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) from 1.18.1 to 1.18.2.
Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/azcore's releases.

sdk/azcore/v1.18.2

1.18.2 (2025-07-31)

Bugs Fixed

  • Fixed a case in which BearerTokenPolicy didn't ensure an authentication error is non-retriable
Commits
  • 362bc89 Prepare azcore v1.18.2 for release (#25033)
  • eb25e76 [AutoPR sdk-resourcemanager/mongocluster/armmongocluster]-generated-from-SDK ...
  • 4975987 Increment package version after release of internal (#25032)
  • 6ca7ffb BearerTokenPolicy ensures authN errors are NonRetriable (#25022)
  • 1827c76 Sync eng/common directory with azure-sdk-tools for PR 11373 (#25019)
  • 3de4755 cosmos: enable support for reading the change feed for through feed ranges (#...
  • 066f6f9 errorinfo.NonRetriable() doesn't wrap errors which are already NonRetriable (...
  • 95910ca Ignore failures when new package isn't indexed yet. (#25017)
  • 76d9191 [Release] sdk/resourcemanager/avs/armavs/2.1.0 (#25025)
  • 2bfa1e3 Add tools for agents (#24962)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/azcore&package-manager=go_modules&previous-version=1.18.1&new-version=1.18.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 5 ++--- go.sum | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 9af56dd2f1..2951ef1efb 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( code.cloudfoundry.org/clock v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0 // indirect @@ -122,7 +122,6 @@ require ( github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gops v0.3.28 // indirect - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/renameio/v2 v2.0.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/mux v1.8.1 // indirect @@ -261,7 +260,7 @@ require ( require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 diff --git a/go.sum b/go.sum index 714053d3bb..3e66bd21be 100644 --- a/go.sum +++ b/go.sum @@ -57,14 +57,14 @@ github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiX github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 h1:Wc1ml6QlJs2BHQ/9Bqu1jiyggbsSjramq2oUmp5WeIo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= @@ -768,7 +768,6 @@ github.com/google/ko v0.15.4/go.mod h1:ZkcmfV91Xt6ZzOBHc/cXXGYnqWdNWDVy/gHoUU9sj github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= From 52b77c1d0622049048f228d5fd7b428f271374d4 Mon Sep 17 00:00:00 2001 From: Mereta Date: Tue, 5 Aug 2025 15:53:54 +0100 Subject: [PATCH 111/448] fix(publicip): Add infrastructure for creating Public IP's (#1797) # Description Adding azure infrastructure for creating public IP's ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. image --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: mereta --- go.mod | 2 + go.sum | 5 + .../azure/create-cluster-with-npm.go | 24 ++++ test/e2e/framework/azure/create-public-ip.go | 109 ++++++++++++++++++ test/e2e/jobs/jobs.go | 29 +++++ 5 files changed, 169 insertions(+) create mode 100644 test/e2e/framework/azure/create-public-ip.go diff --git a/go.mod b/go.mod index 2951ef1efb..0e200753d5 100644 --- a/go.mod +++ b/go.mod @@ -265,6 +265,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 @@ -473,6 +474,7 @@ require ( github.com/google/go-github/v62 v62.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/ko v0.15.4 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect diff --git a/go.sum b/go.sum index 3e66bd21be..ff079dafe6 100644 --- a/go.sum +++ b/go.sum @@ -83,6 +83,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontai github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.6.0/go.mod h1:OWKfCmX4X3Vp2w7GSx1LZn8566tOHJBA6K0IAUVNYx0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 h1:MRPU8Bge2f9tkfG3PCr4vEnqXl8XOSjlhuK3l+8Hvkc= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0/go.mod h1:xYrOYxajQvXMlp6M1E3amlaqPDXspyJxmjqTsGo6Jmw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0/go.mod h1:ceIuwmxDWptoW3eCqSXlnPsZFKh4X+R38dWPv7GS9Vs= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw= @@ -95,6 +97,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0/go.mod h1:jj6P8ybImR+5topJ+eH6fgcemSFBmU6/6bFF8KkwuDI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0 h1:z4YeiSXxnUI+PqB46Yj6MZA3nwb1CcJIkEMDrzUd8Cs= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0/go.mod h1:rko9SzMxcMk0NJsNAxALEGaTYyy79bNRwxgJfrH0Spw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 h1:qBlqTo40ARdI7Pmq+enBiTnejZk2BF+PHgktgG8k3r8= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0/go.mod h1:UmyOatRyQodVpp55Jr5WJmnkmVW4wKfo85uHFmMEjfM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0 h1:HYGD75g0bQ3VO/Omedm54v4LrD3B1cGImuRF3AJ5wLo= @@ -768,6 +772,7 @@ github.com/google/ko v0.15.4/go.mod h1:ZkcmfV91Xt6ZzOBHc/cXXGYnqWdNWDVy/gHoUU9sj github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index ff0708c527..80c4ab88b4 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -35,6 +35,7 @@ type CreateNPMCluster struct { PodCidr string DNSServiceIP string ServiceCidr string + PublicIPs []string } func (c *CreateNPMCluster) Prevalidate() error { @@ -100,6 +101,29 @@ func (c *CreateNPMCluster) Run() error { NodeOSUpgradeChannel: to.Ptr(armcontainerservice.NodeOSUpgradeChannelNodeImage), } + if len(c.PublicIPs) > 0 { + publicIPIDs := make([]*armcontainerservice.ResourceReference, 0, len(c.PublicIPs)) + + for _, ipID := range c.PublicIPs { + fmt.Printf("Adding Public IP ID: %s\n", ipID) + publicIPIDs = append(publicIPIDs, &armcontainerservice.ResourceReference{ + ID: to.Ptr(ipID), + }) + } + + for _, ip := range c.PublicIPs { + fmt.Printf("Public IP ID: %s\n", ip) + } + + if npmCluster.Properties.NetworkProfile.LoadBalancerProfile == nil { + npmCluster.Properties.NetworkProfile.LoadBalancerProfile = &armcontainerservice.ManagedClusterLoadBalancerProfile{ + OutboundIPs: &armcontainerservice.ManagedClusterLoadBalancerProfileOutboundIPs{ + PublicIPs: publicIPIDs, + }, + } + } + } + // Deploy cluster cred, err := azidentity.NewAzureCLICredential(nil) if err != nil { diff --git a/test/e2e/framework/azure/create-public-ip.go b/test/e2e/framework/azure/create-public-ip.go new file mode 100644 index 0000000000..0605e1f74f --- /dev/null +++ b/test/e2e/framework/azure/create-public-ip.go @@ -0,0 +1,109 @@ +package azure + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" +) + +type CreatePublicIP struct { + SubscriptionID string + ResourceGroupName string + Location string + ClusterName string + IPVersion string + IPPrefix string +} + +func (c *CreatePublicIP) Prevalidate() error { + return nil +} + +func (c *CreatePublicIP) Stop() error { + return nil +} + +func (c *CreatePublicIP) Run() error { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatal(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), clusterTimeout) + defer cancel() + + publicIPClient, err := armnetwork.NewPublicIPAddressesClient(c.SubscriptionID, cred, nil) + if err != nil { + return fmt.Errorf("%w: failed to create public IP client", err) + } + + publicIPParams := armnetwork.PublicIPAddress{ + Location: to.Ptr(c.Location), + SKU: &armnetwork.PublicIPAddressSKU{ + Name: to.Ptr(armnetwork.PublicIPAddressSKUNameStandard), + Tier: to.Ptr(armnetwork.PublicIPAddressSKUTierRegional), + }, + Properties: &armnetwork.PublicIPAddressPropertiesFormat{ + PublicIPAllocationMethod: to.Ptr(armnetwork.IPAllocationMethodStatic), + PublicIPAddressVersion: to.Ptr(armnetwork.IPVersion(c.IPVersion)), + IPTags: []*armnetwork.IPTag{ + { + IPTagType: to.Ptr("FirstPartyUsage"), + Tag: to.Ptr("/NonProd"), + }, + }, + }, + } + + var version string + switch c.IPVersion { + case string(armnetwork.IPVersionIPv4): + version = "v4" + case string(armnetwork.IPVersionIPv6): + version = "v6" + default: + return fmt.Errorf("%w: invalid IP version: %s", err, c.IPVersion) + } + + ipName := fmt.Sprintf("%s-%s-%s", c.IPPrefix, c.ClusterName, version) + + poller, err := publicIPClient.BeginCreateOrUpdate(ctx, c.ResourceGroupName, ipName, publicIPParams, nil) + if err != nil { + return fmt.Errorf("%w: failed to create public IP address", err) + } + + notifychan := make(chan struct{}) + go func() { + _, err = poller.PollUntilDone(ctx, &runtime.PollUntilDoneOptions{ + Frequency: 5 * time.Second, + }) + if err != nil { + log.Printf("failed to create Public IP - %s : %v\n", ipName, err) + } else { + log.Printf("Public IP %s created\n", ipName) + } + close(notifychan) + }() + + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return fmt.Errorf("failed to create Public IP: %w", ctx.Err()) + case <-ticker.C: + log.Printf("waiting for Public IP %s to be ready...\n", ipName) + case <-notifychan: + if err != nil { + return fmt.Errorf("received notification, failed to create public IP address: %w", err) + } + return nil + } + } +} diff --git a/test/e2e/jobs/jobs.go b/test/e2e/jobs/jobs.go index 5ce624fc11..f62de4aa78 100644 --- a/test/e2e/jobs/jobs.go +++ b/test/e2e/jobs/jobs.go @@ -1,6 +1,9 @@ package retina import ( + "fmt" + + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" "github.com/microsoft/retina/test/e2e/common" "github.com/microsoft/retina/test/e2e/framework/azure" "github.com/microsoft/retina/test/e2e/framework/generic" @@ -15,9 +18,15 @@ import ( "github.com/microsoft/retina/test/e2e/scenarios/windows" ) +const IPPrefix = "serviceTaggedIp" + func CreateTestInfra(subID, rg, clusterName, location, kubeConfigFilePath string, createInfra bool) *types.Job { job := types.NewJob("Create e2e test infrastructure") + publicIPID := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/publicIPAddresses", subID, clusterName) + publicIPv4FullName := fmt.Sprintf("%s/%s-%s-v4", publicIPID, IPPrefix, clusterName) + publicIPv6FullName := fmt.Sprintf("%s/%s-%s-v6", publicIPID, IPPrefix, clusterName) + if createInfra { job.AddStep(&azure.CreateResourceGroup{ SubscriptionID: subID, @@ -35,11 +44,31 @@ func CreateTestInfra(subID, rg, clusterName, location, kubeConfigFilePath string SubnetAddressSpace: "10.0.0.0/12", }, nil) + job.AddStep(&azure.CreatePublicIP{ + ClusterName: clusterName, + IPVersion: string(armnetwork.IPVersionIPv4), + IPPrefix: IPPrefix, + }, &types.StepOptions{ + SkipSavingParametersToJob: true, + }) + + job.AddStep(&azure.CreatePublicIP{ + ClusterName: clusterName, + IPVersion: string(armnetwork.IPVersionIPv6), + IPPrefix: IPPrefix, + }, &types.StepOptions{ + SkipSavingParametersToJob: true, + }) + job.AddStep(&azure.CreateNPMCluster{ ClusterName: clusterName, PodCidr: "10.128.0.0/9", DNSServiceIP: "192.168.0.10", ServiceCidr: "192.168.0.0/28", + PublicIPs: []string{ + publicIPv4FullName, + publicIPv6FullName, + }, }, nil) job.AddStep(&azure.GetAKSKubeConfig{ From ed9c35a498e8de6025016a708d5fc12609d44841 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 6 Aug 2025 12:20:16 +0100 Subject: [PATCH 112/448] chore(cli): add inspektor gadget to retina shell (#1734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Add inspektor gadget to retina shell. Changes: * Add script to run before bash at creation of pod to mount `debugfs` * Install IG + configure `HOST_ROOT` environment variable * Mount Volume `/run` from host for IG to access runtime data ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ```bash # Run Retina Shell .. # test 1: root@aks-nodepool1-42816995-vmss000001 [ / ]# ig run top_tcp:latest | head RUNTIME.CONTAINERNAME PID TID SRC DST COMM SENT RECEIVED RUNTIME.CONTAINERNAME PID TID SRC DST COMM SENT RECEIVED fortio 1744204 1829243 10.244.2.74:41792 10.0.37.29:8080 fortio 0 B 75 B fortio 1744204 1744223 10.244.2.74:42912 10.0.37.29:8080 fortio 92 B 0 B fortio 1744111 1744138 10.244.2.154:8080 10.244.2.74:43864 fortio 75 B 92 B fortio 1744204 1744223 10.244.2.74:55912 10.0.37.29:8080 fortio 92 B 0 B fortio 1744204 1829243 10.244.2.74:37872 10.0.37.29:8080 fortio 92 B 0 B fortio 1744204 3662728 10.244.2.74:36794 10.0.37.29:8080 fortio 92 B 0 B fortio 1744111 1744138 10.244.2.154:8080 10.244.2.74:57910 fortio 75 B 92 B fortio 1744111 1745004 10.244.2.154:8080 10.244.2.74:43806 fortio 75 B 92 B # test2: root@aks-nodepool1-42816995-vmss000001 [ / ]# ig run trace_dns:latest RUNTIME.CONTAIN… SRC DST NAMESERV… COMM PID TID QR QTYPE NAME RCODE ADDRESS… LATENCY_NS grafana-sc-datas 10.244.2.183:55535 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q A lx-retina--lx-… 0ns coredns 10.244.2.183:55535 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q A lx-retina--lx-… 0ns grafana-sc-datas 10.244.2.183:55535 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.183:55535 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.103:53 10.244.2.183:55535 10.244.2… coredns 4067854 4067854 R A lx-retina--lx-… NameErr… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:55535 10.0.0.10 python 1754576 1754576 R A lx-retina--lx-… NameErr… 610.10µs coredns 10.244.2.103:53 10.244.2.183:55535 10.244.2… coredns 4067854 4067854 R AAAA lx-retina--lx-… NameErr… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:55535 10.0.0.10 python 1754576 1754576 R AAAA lx-retina--lx-… NameErr… 602.50µs grafana-sc-datas 10.244.2.183:45814 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q A lx-retina--lx-… 0ns grafana-sc-datas 10.244.2.183:45814 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q AAAA lx-retina--lx-… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:45814 10.0.0.10 python 1754576 1754576 R A lx-retina--lx-… NameErr… 1.58ms grafana-sc-datas 10.0.0.10:53 10.244.2.183:45814 10.0.0.10 python 1754576 1754576 R AAAA lx-retina--lx-… NameErr… 1.53ms grafana-sc-datas 10.244.2.183:43535 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q A lx-retina--lx-… 0ns coredns 10.244.2.183:43535 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q A lx-retina--lx-… 0ns grafana-sc-datas 10.244.2.183:43535 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.183:43535 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.103:53 10.244.2.183:43535 10.244.2… coredns 4067854 4067854 R A lx-retina--lx-… NameErr… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:43535 10.0.0.10 python 1754576 1754576 R A lx-retina--lx-… NameErr… 494.40µs coredns 10.244.2.103:53 10.244.2.183:43535 10.244.2… coredns 4067854 4067854 R AAAA lx-retina--lx-… NameErr… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:43535 10.0.0.10 python 1754576 1754576 R AAAA lx-retina--lx-… NameErr… 661.40µs grafana-sc-datas 10.244.2.183:47847 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q A lx-retina--lx-… 0ns coredns 10.244.2.183:47847 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q A lx-retina--lx-… 0ns grafana-sc-datas 10.244.2.183:47847 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.183:47847 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.103:53 10.244.2.183:47847 10.244.2… coredns 4067854 4067854 R AAAA lx-retina--lx-… NameErr… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:47847 10.0.0.10 python 1754576 1754576 R AAAA lx-retina--lx-… NameErr… 640.60µs grafana-sc-datas 10.244.2.183:60938 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q A lx-retina--lx-… 0ns coredns 10.244.2.183:60938 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q A lx-retina--lx-… 0ns grafana-sc-datas 10.244.2.183:60938 10.0.0.10:53 10.0.0.10 python 1754576 1754576 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.183:60938 10.244.2.103:53 10.244.2… coredns 4067854 4067854 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.103:53 10.244.2.183:47847 10.244.2… coredns 4067854 4067854 R A lx-retina--lx-… NameErr… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:47847 10.0.0.10 python 1754576 1754576 R A lx-retina--lx-… NameErr… 1.81ms coredns 10.244.2.103:45118 168.63.129.16:53 168.63.1… coredns 4067854 4078662 Q AAAA lx-retina--lx-… 0ns coredns 10.244.2.103:41727 168.63.129.16:53 168.63.1… coredns 4067854 4078662 Q A lx-retina--lx-… 0ns coredns 168.63.129.16:53 10.244.2.103:45118 168.63.1… coredns 4067854 4078662 R AAAA lx-retina--lx-… Success 3.03ms coredns 10.244.2.103:53 10.244.2.183:60938 10.244.2… coredns 4067854 4067854 R AAAA lx-retina--lx-… Success 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:60938 10.0.0.10 python 1754576 1754576 R AAAA lx-retina--lx-… Success 4.30ms coredns 10.244.2.103:53 10.244.2.183:60938 10.244.2… coredns 4067854 4067854 R A lx-retina--lx-… Success 172.179… 0ns grafana-sc-datas 10.0.0.10:53 10.244.2.183:60938 10.0.0.10 python 1754576 1754576 R A lx-retina--lx-… Success 172.179… 4.66ms coredns 168.63.129.16:53 10.244.2.103:41727 168.63.1… coredns 4067854 4078662 R A lx-retina--lx-… Success 172.179… 3.21ms # test 3: root@aks-nodepool1-42816995-vmss000001 [ / ]# ig run top_process:latest RUNTIME.CONTAINERNAME PID COMM CPUUSAGE CPUUSAGERELA… MEMORYRSS MEMORYVIRTUAL MEMORYRELAT… THREADCOUNT STATE UID STARTTIMESTR RUNTIME.CONTAINERNAME PID COMM CPUUSAGE CPUUSAGERELA… MEMORYRSS MEMORYVIRTUAL MEMORYRELAT… THREADCOUNT STATE UID STARTTIMESTR 1 systemd 0.0 0.0 14483456 172789760 0.1 1 S 0 …0T10:07:15Z 10 mm_percpu_wq 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:16Z 100 watchdogd 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 10174 node-problem- 0.0 0.0 3604480 8085504 0.0 1 S 0 …0T10:11:45Z 103 kworker/0:1H- 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:16Z 105 kswapd0 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 10589 node-exporter 0.0 0.0 974848 2961408 0.0 1 S 0 …0T10:11:47Z 10224 node-problem- 0.0 0.0 82599936 3172532224 0.5 15 S 0 …0T10:11:45Z 108 kthrotld 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:16Z 106 ecryptfs-kthr 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 109 nfit 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:16Z 11 rcu_tasks_rud 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 111 scsi_eh_0 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 114 scsi_eh_1 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 112 nvme-wq 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 115 scsi_tmf_0 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 118 scsi_tmf_1 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 117 scsi_eh_2 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 119 nvme-reset-wq 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 12 rcu_tasks_tra 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 120 scsi_eh_3 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 121 scsi_tmf_2 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 122 nvme-delete-w 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 123 scsi_tmf_3 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 124 scsi_eh_4 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 125 scsi_tmf_4 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 126 scsi_eh_5 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 127 scsi_tmf_5 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 128 kworker/1:1H- 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 129 vfio-irqfd-cl 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 13 ksoftirqd/0 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 133 hv_balloon 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:17Z 134 mld 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 135 kworker/3:1H- 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 136 ipv6_addrconf 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 14 rcu_sched 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:16Z 145 kstrp 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 15 migration/0 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:16Z 148 zswap-shrink 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 149 kworker/u9:0 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:17Z 154 jbd2/sda1-8 0.0 0.0 0 0 0.0 1 S 0 …0T10:07:18Z 1541728 kworker/u8:3- 0.0 0.0 0 0 0.0 1 I 0 …3T13:06:10Z 155 ext4-rsv-conv 0.0 0.0 0 0 0.0 1 I 0 …0T10:07:18Z 1618879 sleep 0.0 0.0 1044480 6340608 0.0 1 S 0 …3T14:08:09Z 1656992 kworker/1:1-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:38:28Z 1653373 kworker/0:2-c 0.0 0.0 0 0 0.0 1 I 0 …3T14:35:03Z 1662165 kworker/2:3-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:42:00Z 1662837 kworker/3:2-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:42:39Z 1662164 kworker/2:1-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:42:00Z 1671525 kworker/3:0-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:50:01Z 1671326 kworker/1:3-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:50:00Z 1675970 kworker/u8:1- 0.0 0.0 0 0 0.0 1 I 0 …3T14:53:28Z 1675971 kworker/u8:5- 0.0 0.0 0 0 0.0 1 I 0 …3T14:53:28Z 1675972 kworker/u8:6- 0.0 0.0 0 0 0.0 1 I 0 …3T14:53:28Z 1679482 containerd-sh 0.0 0.0 15396864 1267671040 0.1 13 S 0 …3T14:56:09Z retina-shell 1679552 bash 0.0 0.0 5128192 6201344 0.0 1 S 0 …3T14:56:10Z 1679504 pause 0.0 0.0 4096 995328 0.0 1 S 65535 …3T14:56:10Z 1679931 kworker/1:0-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:56:32Z 1680124 kworker/1:2-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:56:45Z 1680813 kworker/1:4-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:57:10Z 1685035 kworker/u8:0- 0.0 0.0 0 0 0.0 1 I 0 …3T15:00:24Z 1681613 kworker/0:3-a 0.0 0.0 0 0 0.0 1 I 0 …3T14:57:55Z 1680814 kworker/1:5-e 0.0 0.0 0 0 0.0 1 I 0 …3T14:57:10Z # test4: root@aks-nodepool1-42816995-vmss000001 [ / ]# ig run profile_cpu:latest --map-fetch-interval 0 ^CWARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist WARN[0009] stack with ID 4294967282 is lost: lookup: key does not exist RUNTIME.CONTAINERNAME KERNEL_IP COMM PID TID SAMPLES KERN_STACK fortio 18446744072009756834 fortio 1744204 1744218 8 [0]finish_task_switch.is… fortio 18446744072022862826 fortio 1744111 1744139 2 [0]__lock_text_start; [1… fortio 18446744072009756834 fortio 1744204 1744218 1 [0]finish_task_switch.is… fortio 18446744072008772157 fortio 1744204 1829243 1 [0]x64_sys_call; [1]entr… konnectivity-agent 18446744072647485403 proxy-agent 20071 20614 1 [0]bpf_prog_c692d192a4d1… fortio 18446744072022862826 fortio 1744111 1744137 1 [0]__lock_text_start; [1… fortio 0 fortio 1744111 1744225 11 fortio 18446744072022862826 fortio 1744204 3662728 3 [0]__lock_text_start; [1… fortio 18446744072010367488 fortio 1744111 1965298 1 [0]futex_wait_queue_me; … fortio 18446744072020699733 fortio 1744204 1744226 1 [0]ip_finish_output2; [1… fortio 18446744072019852461 fortio 1744111 1744139 1 [0]skb_release_data; [1]… fortio 0 fortio 1744111 1744575 6 fortio 18446744072010235760 fortio 1744204 1829243 1 [0]syscall_trace_enter.c… fortio 18446744072022805100 fortio 1744111 1744137 1 [0]syscall_enter_from_us… fortio 0 fortio 1744111 1744651 9 fortio 18446744072020699544 fortio 1744111 1744225 1 [0]ip_finish_output2; [1… fortio 18446744072010270080 fortio 1744111 1744575 1 [0]hrtimer_try_to_cancel… fortio 18446744072012664714 fortio 1744111 1744651 1 [0]__fget_light; [1]do_e… fortio 18446744072649004944 fortio 1744111 1744225 1 [0]bpf_prog_c692d192a4d1… fortio 18446744072009756834 fortio 1744111 1744651 1 [0]finish_task_switch.is… fortio 18446744072021103375 fortio 1744204 1744223 1 [0]fib_table_lookup; [1]… fortio 18446744072020847664 fortio 1744111 1744225 1 [0]tcp_small_queue_check… fortio 18446744072647501157 fortio 1744111 1744651 1 [0]bpf_prog_c692d192a4d1… fortio 18446744072019978352 fortio 1744111 1744651 1 [0]dev_queue_xmit; [1]ip… fortio 18446744072020844671 fortio 1744204 1744226 1 [0]tcp_event_new_data_se… fortio 18446744072022862826 fortio 1744204 1744223 2 [0]__lock_text_start; [1… coredns 18446744072019784970 coredns 4067854 4067908 1 [0]sock_recvmsg; [1]sock… fortio 18446744072010604336 fortio 1744111 1744225 1 [0]audit_filter_syscall;… fortio 18446744072020129911 fortio 1744204 1829243 1 [0]sk_filter_trim_cap; [… fortio 18446744072012405713 fortio 1744204 1744223 1 [0]mem_cgroup_charge_skm… fortio 18446744072015392176 fortio 1744111 1965298 1 [0]_copy_from_user; [1]_… fortio 18446744072020896941 fortio 1744111 1744575 1 [0]tcp_v4_do_rcv; [1]tcp… konnectivity-agent 0 proxy-agent 20071 20071 1 fortio 18446744072014241172 fortio 1744204 3662728 1 [0]security_sock_rcv_skb… node-driver-registrar 0 runc:[2:INIT] 1689249 1689249 1 fortio 18446744072010236990 fortio 1744111 1744137 1 [0]syscall_exit_work; [1… fortio 0 fortio 1744204 1744223 3 fortio 0 fortio 1744111 1965298 14 ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- shell/Dockerfile | 18 ++++++++++++++++++ shell/README.md | 23 +++++++++++++++++++++++ shell/manifests.go | 38 +++++++++++++++++++++++++++----------- shell/manifests_test.go | 14 ++++++++++---- 4 files changed, 78 insertions(+), 15 deletions(-) diff --git a/shell/Dockerfile b/shell/Dockerfile index 642881a55b..8642af0478 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -26,8 +26,26 @@ RUN tdnf install -y \ tar \ file \ bpftool \ + ig \ && tdnf clean all +# Create the entrypoint script to mount debugfs +SHELL ["/bin/bash", "-c"] + +RUN echo $'#!/bin/bash\n\ +if ! mountpoint -q /sys/kernel/debug; then\n\ +mount -t debugfs none /sys/kernel/debug\n\ +fi\n\ +exec "$@"' > /usr/local/bin/entrypoint.sh; + +# Set the host root directory for IG +ENV HOST_ROOT=/host + +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Set the entrypoint +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + # Re-use existing arg from Makefile target "container-docker" # https://github.com/microsoft/retina/blob/main/Makefile#L224 ARG GOARCH=amd64 diff --git a/shell/README.md b/shell/README.md index abe3251a7b..14e6c3252d 100644 --- a/shell/README.md +++ b/shell/README.md @@ -6,6 +6,7 @@ Retina CLI provides a command to launch an interactive shell in a node or pod fo * The container runs an image built from the Dockerfile in this directory. The image is based on Azure Linux and includes commonly-used networking tools. * The [pwru](https://github.com/cilium/pwru) tool is bundled in the image for advanced kernel packet tracing. * bpftool is also included for eBPF debugging. +* [Inspektor Gadget (ig)](https://inspektor-gadget.io/) is included for additional debugging capabilities. For testing, you can override the image used by `retina shell` either with CLI arguments (`--retina-shell-image-repo` and `--retina-shell-image-version`) or environment variables @@ -36,4 +37,26 @@ pwru --help bpftool --help ``` +To use `ig`, you need to add the `--mount-host-filesystem`, `--apparmor-unconfined` and `--seccomp-unconfined` flags, along with the following capabilities: + +* `NET_ADMIN` +* `SYS_ADMIN` +* `SYS_RESOURCE` +* `SYSLOG` +* `IPC_LOCK` +* `SYS_PTRACE` +* `NET_RAW` + +```sh +# Node debugging +kubectl retina shell aks-nodepool1-42816995-vmss000001 --capabilities=NET_ADMIN,SYS_ADMIN,SYS_RESOURCE,SYSLOG,IPC_LOCK,SYS_PTRACE,NET_RAW --mount-host-filesystem --apparmor-unconfined --seccomp-unconfined +``` + +Once inside the shell, you can run: + +```sh +ig -h +ig run trace_dns:latest +``` + Currently only Linux is supported; Windows support will be added in the future. diff --git a/shell/manifests.go b/shell/manifests.go index 4dd2188ff4..3d78030fa4 100644 --- a/shell/manifests.go +++ b/shell/manifests.go @@ -54,19 +54,35 @@ func hostNetworkPodForNodeDebug(config Config, debugPodNamespace, nodeName strin } if config.MountHostFilesystem || config.AllowHostFilesystemWrite { - pod.Spec.Volumes = append(pod.Spec.Volumes, v1.Volume{ - Name: "host-filesystem", - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{ - Path: "/", + pod.Spec.Volumes = append(pod.Spec.Volumes, + v1.Volume{ + Name: "host-filesystem", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/", + }, + }, + }, + v1.Volume{ + Name: "run", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/run", + }, }, }, - }) - pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{ - Name: "host-filesystem", - MountPath: "/host", - ReadOnly: !config.AllowHostFilesystemWrite, - }) + ) + pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, + v1.VolumeMount{ + Name: "host-filesystem", + MountPath: "/host", + ReadOnly: !config.AllowHostFilesystemWrite, + }, + v1.VolumeMount{ + Name: "run", + MountPath: "/run", + }, + ) } if config.AppArmorUnconfined { diff --git a/shell/manifests_test.go b/shell/manifests_test.go index 840d7d2e49..091e3c21ca 100644 --- a/shell/manifests_test.go +++ b/shell/manifests_test.go @@ -68,12 +68,15 @@ func TestHostNetworkPodForNodeDebugWithMountHostFilesystem(t *testing.T) { MountHostFilesystem: true, } pod := hostNetworkPodForNodeDebug(config, "kube-system", "node0001") - assert.Len(t, pod.Spec.Volumes, 1) + assert.Len(t, pod.Spec.Volumes, 2) assert.Equal(t, "host-filesystem", pod.Spec.Volumes[0].Name) - assert.Len(t, pod.Spec.Containers[0].VolumeMounts, 1) + assert.Len(t, pod.Spec.Containers[0].VolumeMounts, 2) assert.Equal(t, "host-filesystem", pod.Spec.Containers[0].VolumeMounts[0].Name) assert.Equal(t, "/host", pod.Spec.Containers[0].VolumeMounts[0].MountPath) + assert.Equal(t, "run", pod.Spec.Containers[0].VolumeMounts[1].Name) + assert.Equal(t, "/run", pod.Spec.Containers[0].VolumeMounts[1].MountPath) assert.True(t, pod.Spec.Containers[0].VolumeMounts[0].ReadOnly) + assert.False(t, pod.Spec.Containers[0].VolumeMounts[1].ReadOnly) } func TestHostNetworkPodForNodeDebugWithMountHostFilesystemWithWriteAccess(t *testing.T) { @@ -82,10 +85,13 @@ func TestHostNetworkPodForNodeDebugWithMountHostFilesystemWithWriteAccess(t *tes AllowHostFilesystemWrite: true, } pod := hostNetworkPodForNodeDebug(config, "kube-system", "node0001") - assert.Len(t, pod.Spec.Volumes, 1) + assert.Len(t, pod.Spec.Volumes, 2) assert.Equal(t, "host-filesystem", pod.Spec.Volumes[0].Name) - assert.Len(t, pod.Spec.Containers[0].VolumeMounts, 1) + assert.Len(t, pod.Spec.Containers[0].VolumeMounts, 2) assert.Equal(t, "host-filesystem", pod.Spec.Containers[0].VolumeMounts[0].Name) assert.Equal(t, "/host", pod.Spec.Containers[0].VolumeMounts[0].MountPath) + assert.Equal(t, "run", pod.Spec.Containers[0].VolumeMounts[1].Name) + assert.Equal(t, "/run", pod.Spec.Containers[0].VolumeMounts[1].MountPath) assert.False(t, pod.Spec.Containers[0].VolumeMounts[0].ReadOnly) + assert.False(t, pod.Spec.Containers[0].VolumeMounts[1].ReadOnly) } From 750fddd9b06ed70d33d723c4cb730ef113761c61 Mon Sep 17 00:00:00 2001 From: Mereta Date: Wed, 6 Aug 2025 15:50:46 +0100 Subject: [PATCH 113/448] fix(cve): Upgrading base golang image to fix CVE's (#1794) # Description #1791 Indicated presence of some CVE's in agent & operator images. Bumping golang base image to address some of them. Some CVE's still coming from `tdnf` installed tools in agent Dockerfile. image image ## Related Issue #1791 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Operator all CVE's resolved image Agent CVE's not resolved yet image --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: mereta --- cli/Dockerfile | 4 ++-- controller/Dockerfile | 8 ++++---- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-2019 | 6 +++--- controller/Dockerfile.windows-2022 | 6 +++--- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 6 +++--- controller/Dockerfile.windows-retina-oss-build | 8 ++++---- hack/tools/kapinger/Dockerfile | 2 +- hack/tools/toolbox/Dockerfile | 2 +- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2019 | 6 +++--- operator/Dockerfile.windows-2022 | 6 +++--- test/image/Dockerfile | 4 ++-- 15 files changed, 37 insertions(+), 37 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 5823178bf4..e24332209c 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index 056e26d670..1d431bd777 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -2,8 +2,8 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d AS azurelinux-core @@ -12,10 +12,10 @@ FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599a FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS azurelinux-distroless # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:862b24ccf5e399fc3bea746c7ac68c16f3fbcfa199532a3e506b7e03e57217b9 AS ltsc2019 +FROM mcr.microsoft.com/windows/servercore@sha256:2a7cfebaed9241227ad68b1fc7cb764867ea1c56624ece03f926eb8bdf0c998f AS ltsc2019 # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:c489e1737a833a111f0f35b28257b1071d30b6db6b9ee50e88b7c08b901efc67 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:3281482945016cdaefbe417edd8338de8119e077b6941f74e78b050da1b7bd97 AS ltsc2022 # build stages diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 933e871477..a58e772765 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index c88d547d60..1d45efa488 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index 24ca5b917a..bf1640611b 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder # Build args ARG VERSION @@ -17,7 +17,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/ca # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:862b24ccf5e399fc3bea746c7ac68c16f3fbcfa199532a3e506b7e03e57217b9 as final +FROM mcr.microsoft.com/windows/servercore@sha256:2a7cfebaed9241227ad68b1fc7cb764867ea1c56624ece03f926eb8bdf0c998f as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 7963d88fc9..58da3c8b38 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder # Build args ARG VERSION @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/co RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:c489e1737a833a111f0f35b28257b1071d30b6db6b9ee50e88b7c08b901efc67 as final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:3281482945016cdaefbe417edd8338de8119e077b6941f74e78b050da1b7bd97 as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 545faf9a86..002630d676 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:e88cdedc8ab0299e85c1c54dede140d4f4c1c4ee595b3d9d37b4a9a103eb0a2e AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:f9c24af183306a0a2fa55601909601f347694573a14f03cd2afe9400d0fde01b AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index dcddfb32f2..e52d870861 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:e88cdedc8ab0299e85c1c54dede140d4f4c1c4ee595b3d9d37b4a9a103eb0a2e AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:f9c24af183306a0a2fa55601909601f347694573a14f03cd2afe9400d0fde01b AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:23fa4e796f4d02d462beadb844f8985ca4583b1b0f75295137f5968dab255b09 AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:9a57174ce85e979529e4f0cd58dff2e837b65fc7832b7585b4882f6cce0e255d AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index be4569c473..2e6c88ea90 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -2,11 +2,11 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# mcr.microsoft.com/windows/servercore:ltsc2019 -FROM mcr.microsoft.com/windows/servercore@sha256:6fdf140282a2f809dae9b13fe441635867f0a27c33a438771673b8da8f3348a4 AS ltsc2019 +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/servercore@sha256:2a7cfebaed9241227ad68b1fc7cb764867ea1c56624ece03f926eb8bdf0c998f AS ltsc2019 -# mcr.microsoft.com/windows/servercore:ltsc2022 -FROM mcr.microsoft.com/windows/servercore@sha256:45952938708fbde6ec0b5b94de68bcdec3f8c838be018536b1e9e5bd95e6b943 AS ltsc2022 +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/windows/servercore@sha256:3281482945016cdaefbe417edd8338de8119e077b6941f74e78b050da1b7bd97 AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 45aa1e2af5..2593300fd3 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.4 AS builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.5 AS builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index e069c5b054..02a4bec438 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.4 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.5 AS build ADD . . WORKDIR /go/toolbox/ RUN CGO_ENABLED=0 GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 079cc31b27..03b6e8a1cc 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index 65097f97d7..4cc6d24cf6 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder # Build args ARG VERSION @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:7c720f345ff7784cee12a5464bb5d5222c6348bd6da2cd29d666e49867958b0e +FROM mcr.microsoft.com/windows/nanoserver@sha256:c357ed591af7b24f2d4a12b1947da5e6ebe559d89f41471f6928902c7cda7206 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 8e596795db..3b9feec346 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder # Build args ARG VERSION @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:23fa4e796f4d02d462beadb844f8985ca4583b1b0f75295137f5968dab255b09 +FROM mcr.microsoft.com/windows/nanoserver@sha256:9a57174ce85e979529e4f0cd58dff2e837b65fc7832b7585b4882f6cce0e255d COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 20c40e6723..c73331acda 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.4-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:250d01e55a37bd79d7014ae83f9f50aa6fa5570ca910e7f19faeff4bb0132ae1 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder ENV CGO_ENABLED=0 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From da220227685ddbef8e185a1e5d71b5def8f64a6c Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Fri, 8 Aug 2025 20:59:49 +0000 Subject: [PATCH 114/448] fix(capture): ignore known copy failure and fix iptables issue (#1798) # Description This is a port of the changes in PR https://github.com/microsoft/retina/pull/903 because that PR has gone stale. The PR addresses a known failure when copying files which don't implement a Read(), and also adds error handling to how the IP tables are obtained. ## Related Issue https://github.com/microsoft/retina/issues/895 https://github.com/microsoft/retina/issues/1728 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Testing [BEFORE] Capture on latest commit of main: `RETINA_AGENT_IMAGE="ghcr.io/microsoft/retina/retina-agent:52b77c1-linux-amd64" ./artifacts/kubectl-retina capture create --name iptables-v36 --duration 5s --debug` image [AFTER] Capture on latest commit of this PR: `RETINA_AGENT_IMAGE="ghcr.io/kamilprz/retina/retina-agent:v1.0.0-rc1-28-ga24a3ba-linux-amd64" ./artifacts/kubectl-retina capture create --name iptables-capt --duration 5s --debug` image Upon downloading the capture and extracting it, we can see in `iptables-rules.txt` that nft mode was used. {C037A30D-BA91-4483-BB74-32C6A5B6029E} --------- Signed-off-by: Kamil --- pkg/capture/provider/network_capture_unix.go | 108 ++++++++++++++----- pkg/capture/provider/network_capture_win.go | 15 +-- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/pkg/capture/provider/network_capture_unix.go b/pkg/capture/provider/network_capture_unix.go index 04081fba53..9a6f6bd207 100644 --- a/pkg/capture/provider/network_capture_unix.go +++ b/pkg/capture/provider/network_capture_unix.go @@ -21,12 +21,21 @@ import ( captureConstants "github.com/microsoft/retina/pkg/capture/constants" "github.com/microsoft/retina/pkg/capture/file" "github.com/microsoft/retina/pkg/log" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type iptablesMode string + +const ( + legacyIptablesMode iptablesMode = "legacy" + nftIptablesMode iptablesMode = "nft" ) var ( errTcpdumpCommandNotConstructed = errors.New("tcpdump command is not constructed with expected arguments") errTcpdumpStopFailed = errors.New("tcpdump stop failed") + errIptablesUnavilable = errors.New("no iptables command is available") + errIptablesLegacySaveFailed = errors.New("failed to run iptables-legacy-save") + errIptablesNftSaveFailed = errors.New("failed to run iptables-nft-save") ) // constructTcpdumpCommand creates a tcpdump command with the appropriate arguments @@ -75,10 +84,8 @@ func constructTcpdumpCommand(captureFilePath string) *exec.Cmd { type NetworkCaptureProvider struct { NetworkCaptureProviderCommon - TmpCaptureDir string - CaptureName string - NodeHostName string - StartTimestamp *metav1.Time + TmpCaptureDir string + Filename file.CaptureFilename l *log.ZapLogger } @@ -100,9 +107,8 @@ func (ncp *NetworkCaptureProvider) Setup(filename file.CaptureFilename) (string, ncp.l.Info("Created temporary folder for network capture", zap.String("capture temporary folder", captureFolderDir)) ncp.TmpCaptureDir = captureFolderDir - ncp.CaptureName = filename.CaptureName - ncp.NodeHostName = filename.NodeHostname - ncp.StartTimestamp = filename.StartTimestamp + ncp.Filename = filename + return ncp.TmpCaptureDir, nil } @@ -110,8 +116,7 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil ctx, cancel := context.WithTimeout(ctx, time.Duration(duration)*time.Second) defer cancel() - filename := file.CaptureFilename{CaptureName: ncp.CaptureName, NodeHostname: ncp.NodeHostName, StartTimestamp: ncp.StartTimestamp} - captureFileName := filename.String() + ".pcap" + captureFileName := ncp.Filename.String() + ".pcap" captureFilePath := filepath.Join(ncp.TmpCaptureDir, captureFileName) // Remove the folder in case it already exists to mislead the file size check. @@ -228,18 +233,23 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil } type command struct { - name string - args []string - description string + name string + args []string + description string + ignoreFailure bool } func (ncp *NetworkCaptureProvider) CollectMetadata() error { ncp.l.Info("Start to collect network metadata") - iptablesMode := obtainIptablesMode() - ncp.l.Info(fmt.Sprintf("Iptables mode %s is used", iptablesMode)) - iptablesSaveCmdName := "iptables-" + iptablesMode + "-save" - iptablesCmdName := "iptables-" + iptablesMode + iptablesModeName, err := obtainIptablesMode(ncp.l) + if err != nil { + return fmt.Errorf("failed to determine iptables modes. %w", err) + } + + ncp.l.Info(fmt.Sprintf("Iptables mode %s is used", iptablesModeName)) + iptablesSaveCmdName := fmt.Sprintf("iptables-%s-save", iptablesModeName) + iptablesCmdName := fmt.Sprintf("iptables-%s", iptablesModeName) metadataList := []struct { commands []command @@ -325,6 +335,9 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { name: "cp", args: []string{"-r", "/proc/sys/net", filepath.Join(ncp.TmpCaptureDir, "proc-sys-net")}, description: "kernel networking configuration", + // Errors will occur when copying kernel networking configuration for not all files under /proc/sys/net are + // readable, like '/proc/sys/net/ipv4/route/flush', which doesn't implement the read function. + ignoreFailure: true, }, }, }, @@ -335,10 +348,10 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { ncp.processMetadataFile(metadata) } else { for _, command := range metadata.commands { - cmd := exec.Command(command.name, command.args...) // #nosec G204 -- commands are predefined system utilities with safe arguments + cmd := exec.CommandContext(context.Background(), command.name, command.args...) // nolint:gosec // no sensitive data // Errors will when copying kernel networking configuration for not all files under /proc/sys/net are // readable, like '/proc/sys/net/ipv4/route/flush', which doesn't implement the read function. - if output, err := cmd.CombinedOutput(); err != nil { + if output, err := cmd.CombinedOutput(); err != nil && !command.ignoreFailure { // Don't return for error to continue capturing following network metadata. ncp.l.Error("Failed to execute command", zap.String("command", cmd.String()), zap.String("output", string(output)), zap.Error(err)) } @@ -371,7 +384,7 @@ func (ncp *NetworkCaptureProvider) processMetadataFile(metadata struct { // Print headlines for all commands in output file. cmds := []*exec.Cmd{} for _, command := range metadata.commands { - cmd := exec.Command(command.name, command.args...) // #nosec G204 -- commands are predefined system utilities with safe arguments + cmd := exec.CommandContext(context.Background(), command.name, command.args...) // nolint:gosec // no sensitive data cmds = append(cmds, cmd) commandSummary := fmt.Sprintf("%s(%s)\n", cmd.String(), command.description) if _, err := outfile.WriteString(commandSummary); err != nil { @@ -404,21 +417,58 @@ func (ncp *NetworkCaptureProvider) processMetadataFile(metadata struct { } func (ncp *NetworkCaptureProvider) Cleanup() error { - ncp.l.Info("Cleanup network capture", zap.String("capture name", ncp.CaptureName), zap.String("temporary dir", ncp.TmpCaptureDir)) + ncp.l.Info("Cleanup network capture", zap.String("capture name", ncp.Filename.CaptureName), zap.String("temporary dir", ncp.TmpCaptureDir)) ncp.NetworkCaptureProviderCommon.Cleanup() return nil } -func obtainIptablesMode() string { +// obtainIptablesMode return the available iptables mode, and returns empty when no iptables is available. +func obtainIptablesMode(logger *log.ZapLogger) (iptablesMode, error) { // Since iptables v1.8, nf_tables are introduced as an improvement of legacy iptables, but provides the same user // interface as legacy iptables through iptables-nft command. // based on: https://github.com/kubernetes-sigs/iptables-wrappers/blob/97b01f43a8e8db07840fc4b95e833a37c0d36b12/iptables-wrapper-installer.sh - legacySaveOut, _ := exec.Command("iptables-legacy-save").CombinedOutput() - legacySaveLineNum := len(strings.Split(string(legacySaveOut), "\n")) - nftSaveOut, _ := exec.Command("iptables-nft-save").CombinedOutput() - nftSaveLineNum := len(strings.Split(string(nftSaveOut), "\n")) - if legacySaveLineNum > nftSaveLineNum { - return "legacy" + + // When both iptables modes available, we choose the one with more rules, because the other one normally outputs empty rules. + nftIptablesModeAvaiable := true + legacyIptablesModeAvaiable := true + legacySaveLineNum := 0 + nftSaveLineNum := 0 + if _, err := exec.LookPath("iptables-legacy-save"); err != nil { + legacyIptablesModeAvaiable = false + logger.Info("iptables-legacy-save is not available", zap.Error(err)) + } else { + legacySaveOut, err := exec.CommandContext(context.Background(), "iptables-legacy-save").CombinedOutput() + if err != nil { + return "", fmt.Errorf("%w: %w", errIptablesLegacySaveFailed, err) + } + legacySaveLineNum = len(strings.Split(string(legacySaveOut), "\n")) + } + + if _, err := exec.LookPath("iptables-nft-save"); err != nil { + nftIptablesModeAvaiable = false + logger.Info("iptables-nft-save is not available", zap.Error(err)) + } else { + nftSaveOut, err := exec.CommandContext(context.Background(), "iptables-nft-save").CombinedOutput() + if err != nil { + return "", fmt.Errorf("%w: %w", errIptablesNftSaveFailed, err) + } + nftSaveLineNum = len(strings.Split(string(nftSaveOut), "\n")) + } + + if nftIptablesModeAvaiable && legacyIptablesModeAvaiable { + if legacySaveLineNum > nftSaveLineNum { + return legacyIptablesMode, nil + } + return nftIptablesMode, nil } - return "nft" + + if nftIptablesModeAvaiable { + return nftIptablesMode, nil + } + + if legacyIptablesModeAvaiable { + return legacyIptablesMode, nil + } + + return "", errIptablesUnavilable } diff --git a/pkg/capture/provider/network_capture_win.go b/pkg/capture/provider/network_capture_win.go index 57a5e7e930..1d01adcf7e 100644 --- a/pkg/capture/provider/network_capture_win.go +++ b/pkg/capture/provider/network_capture_win.go @@ -18,7 +18,6 @@ import ( "time" "go.uber.org/zap" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" captureConstants "github.com/microsoft/retina/pkg/capture/constants" "github.com/microsoft/retina/pkg/capture/file" @@ -27,11 +26,8 @@ import ( type NetworkCaptureProvider struct { NetworkCaptureProviderCommon - TmpCaptureDir string - CaptureName string - NodeHostName string - StartTimestamp *metav1.Time - Filename file.CaptureFilename + TmpCaptureDir string + Filename file.CaptureFilename l *log.ZapLogger } @@ -53,10 +49,7 @@ func (ncp *NetworkCaptureProvider) Setup(filename file.CaptureFilename) (string, ncp.l.Info("Created temporary folder for network capture", zap.String("capture temporary folder", captureFolderDir)) ncp.TmpCaptureDir = captureFolderDir - ncp.CaptureName = filename.CaptureName - ncp.NodeHostName = filename.NodeHostname - ncp.StartTimestamp = filename.StartTimestamp - ncp.Filename = file.CaptureFilename{CaptureName: ncp.CaptureName, NodeHostname: ncp.NodeHostName, StartTimestamp: ncp.StartTimestamp} + ncp.Filename = filename return ncp.TmpCaptureDir, nil } @@ -302,7 +295,7 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { } func (ncp *NetworkCaptureProvider) Cleanup() error { - ncp.l.Info("Cleanup network capture", zap.String("capture name", ncp.CaptureName), zap.String("temporary dir", ncp.TmpCaptureDir)) + ncp.l.Info("Cleanup network capture", zap.String("capture name", ncp.Filename.CaptureName), zap.String("temporary dir", ncp.TmpCaptureDir)) ncp.NetworkCaptureProviderCommon.Cleanup() return nil } From 99eab4cf324c330a9d1514257b6f9ae67601f0aa Mon Sep 17 00:00:00 2001 From: Anubhab Majumdar Date: Fri, 8 Aug 2025 20:48:33 -0500 Subject: [PATCH 115/448] fix(localctx+win): Fix the helm insatll command for localCtx (#1807) # Description - Disable operator installation for `localCtx` (not needed) - Windows configmap is missing `enableAnnotations` config ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ```bash $ kg cm retina-config-win -oyaml apiVersion: v1 data: config.yaml: "apiServer:\n host: 0.0.0.0\n port: 10093\nlogLevel: info\nenabledPlugin: [\"hnsstats\"]\nmetricsInterval: \nmetricsIntervalDuration: 10s\nenableTelemetry: false\nenablePodLevel: true\nremoteContext: false\nenableAnnotations: true\ntelemetryInterval: 15m" kind: ConfigMap ... ``` ```bash $ kg po -A -owide | grep -i retina kube-system retina-agent-d47xk 1/1 Running 0 7m25s 10.224.0.4 aks-nodepool1-31204792-vmss000000 kube-system retina-agent-g9m4b 1/1 Running 0 6m51s 10.224.0.5 aks-nodepool1-31204792-vmss000001 kube-system retina-agent-kfdwx 1/1 Running 0 6m17s 10.224.0.6 aks-nodepool1-31204792-vmss000002 kube-system retina-agent-win-52wkl 1/1 Running 7 (12m ago) 32m 10.224.0.7 akswin000000 kube-system retina-agent-win-j4r4f 1/1 Running 6 (9m27s ago) 29m 10.224.0.8 akswin2000000 ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Anubhab Majumdar --- Makefile | 4 ++-- .../manifests/controller/helm/retina/templates/configmap.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 210a64505a..dd6ae3cce1 100644 --- a/Makefile +++ b/Makefile @@ -487,8 +487,8 @@ helm-install-advanced-local-context: manifests --set image.pullPolicy=Always \ --set logLevel=info \ --set os.windows=true \ - --set operator.enabled=true \ - --set operator.enableRetinaEndpoint=true \ + --set operator.enabled=false \ + --set operator.enableRetinaEndpoint=false \ --set operator.repository=$(IMAGE_REGISTRY)/$(RETINA_OPERATOR_IMAGE) \ --skip-crds \ --set enabledPlugin_linux="\[dropreason\,packetforward\,linuxutil\,dns\,packetparser\]" \ diff --git a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml index 65075bc424..da0de325f2 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml @@ -49,6 +49,7 @@ data: enableTelemetry: {{ .Values.enableTelemetry }} enablePodLevel: {{ .Values.enablePodLevel }} remoteContext: {{ .Values.remoteContext }} + enableAnnotations: {{ .Values.enableAnnotations }} telemetryInterval: {{ .Values.daemonset.telemetryInterval }} {{- end}} From eb048674831fb566f006c4283c0f5f243a1a6d39 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Mon, 11 Aug 2025 08:58:58 +0100 Subject: [PATCH 116/448] fix: enable annotations (#1806) # Description This PR is replacing #1471 which is now closed. ## Feature description When using option `enableAnnotation: true`, metrics should only be generated for pods annotated with `retina.sh: observe` or pods in a namespace with that annotation. There's an exception regarding DNS plugin, which uses inspektor: https://github.com/microsoft/retina/blob/750fddd9b06ed70d33d723c4cb730ef113761c61/pkg/plugin/dns/dns_linux.go#L7-L13 https://github.com/microsoft/retina/blob/750fddd9b06ed70d33d723c4cb730ef113761c61/pkg/plugin/dns/dns_linux.go#L52-L58 ## Bug When enableAnnotation: true advanced metrics are still being generated for all pods. This was introduced in #1102 ## Explanation PacketParser plugin overrides the file `pkg/plugin/packetparser/_cprog/dynamic.h` during runtime: https://github.com/microsoft/retina/blob/750fddd9b06ed70d33d723c4cb730ef113761c61/pkg/plugin/packetparser/packetparser_linux.go#L120-L121 The bug was introduced by changing the code below to inside `if` block: https://github.com/microsoft/retina/blob/750fddd9b06ed70d33d723c4cb730ef113761c61/pkg/plugin/packetparser/packetparser_linux.go#L96 So when `bypassLookupIPOfInterest := 0` (which is default), variable `BYPASS_LOOKUP_IP_OF_INTEREST` does not get defined and the block below gets skipped, generating metrics for all pods: https://github.com/microsoft/retina/blob/750fddd9b06ed70d33d723c4cb730ef113761c61/pkg/plugin/packetparser/_cprog/packetparser.c#L151-L158 ## Fix 1. Move code back to its original position 2. Adjust documentation to reflect actual behavior: 2.a. Metrics are not generated for all pods in `kube-system` by default 2.b. DNS plugin does is not configured to filter IPs ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ### Without annotations Retina with annotations enabled: image Namespaces without annotations: image Fortio deployments communicating in `traffic`: image Deployment to test DNS in `default`: image `curl` execution from pod in `default` namespace: image `networkobservability_adv_forward_bytes` for both namespaces: image image `networkobservability_adv_dns_request_count` for `default`: image ### Add annotation to `default` namespace `default` namespace with annotation: image New `curl` execution from pod in `default` namespace: image `networkobservability_adv_forward_bytes` for `default`: image `networkobservability_adv_dns_request_count` for `default`: image ### Add annotation to `traffic` namespace `traffic` namespace with annotation: image `networkobservability_adv_forward_bytes` for `traffic`: image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos Signed-off-by: Alex Castilio Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/03-Metrics/annotations.md | 9 ++++++--- pkg/plugin/packetparser/packetparser_linux.go | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/03-Metrics/annotations.md b/docs/03-Metrics/annotations.md index bd4282445c..13592e7e42 100644 --- a/docs/03-Metrics/annotations.md +++ b/docs/03-Metrics/annotations.md @@ -1,13 +1,16 @@ # Annotations +**This feature is only available in Standard Control Plane.** + Annotations let you specify which Pods to observe (create metrics for). -To configure this, specify `enableAnnotations=true` in Retina's [helm installation](../02-Installation/01-Setup.md) or [ConfigMap](../02-Installation/03-Config.md). + +To enable it, specify `enableAnnotations=true` in Retina's Standard Control Plane [helm installation](../02-Installation/01-Setup.md) or [ConfigMap](../02-Installation/03-Config.md). You can then add the annotation `retina.sh: observe` to either: - individual Pods - Namespaces (to observe all the Pods in the namespace). -An exception: currently all Pods in `kube-system` are always monitored. +**Note 1**: If you enable Annotations, you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. -**Note**: If you enable Annotations, you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. +**Note 2**: Currently the DNS plugin does not consider annotations when generating DNS metrics, so it generates metrics for all pods. diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index 002e04a057..9baade8e67 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -93,8 +93,8 @@ func (p *packetParser) Generate(ctx context.Context) error { if p.cfg.BypassLookupIPOfInterest { p.l.Info("bypassing lookup IP of interest") bypassLookupIPOfInterest = 1 - st = fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n", bypassLookupIPOfInterest) } + st = fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n", bypassLookupIPOfInterest) conntrackMetrics := 0 // Check if packetparser has Conntrack metrics enabled. From 439754dd817fed29b0be7a9d9493b2bdb0fca507 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:11:02 +0000 Subject: [PATCH 117/448] deps: bump google.golang.org/grpc from 1.74.0 to 1.74.2 (#1769) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.74.0 to 1.74.2.
Release notes

Sourced from google.golang.org/grpc's releases.

Release 1.74.2

API Changes

  • balancer: add ExitIdle method to Balancer interface. Earlier, implementing this method was optional. (#8367)

Behavior Changes

  • xds: Remove the GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST environment variable that allows disabling the least request balancer with xDS. Least request was made available by default with xDS in v1.72.0. (#8248)
  • server: allow 0s grpc-timeout header values, which older gRPC-Java versions could send. This restores the behavior of grpc-go before v1.73.0. (#8439)

Bug Fixes

  • googledirectpath: avoid logging the error message Attempt to set a bootstrap configuration... when creating multiple directpath channels. (#8419)

Performance Improvements

  • transport: reduce heap allocations by pooling objects and avoiding method-to-closure conversions. (#8361)
  • transport: reduce heap allocations by re-using mem.Reader objects. (#8360)

Documentation

  • examples: add examples to demonstrate enabling experimental metrics using the OpenTelemetry plugin. (#8388)

Release 1.74.1

Version 1.74.1 retracts release v1.74.0 and itself. Release 1.74.0 was accidentally tagged on the wrong commit and should not be used. Version 1.73.0 should be used until 1.74.2 is released.

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.74.0&new-version=1.74.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0e200753d5..81c4029366 100644 --- a/go.mod +++ b/go.mod @@ -306,7 +306,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - google.golang.org/grpc v1.74.0 + google.golang.org/grpc v1.74.2 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 diff --git a/go.sum b/go.sum index ff079dafe6..8f5a512a52 100644 --- a/go.sum +++ b/go.sum @@ -1874,8 +1874,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.74.0 h1:sxRSkyLxlceWQiqDofxDot3d4u7DyoHPc7SBXMj8gGY= -google.golang.org/grpc v1.74.0/go.mod h1:NZUaK8dAMUfzhK6uxZ+9511LtOrk73UGWOFoNvz7z+s= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From e25d0f33b68c5ba7c52f281de330695766859dac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:20:49 -0400 Subject: [PATCH 118/448] deps: bump actions/checkout from 4.2.2 to 5.0.0 (#1809) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0.
Release notes

Sourced from actions/checkout's releases.

v5.0.0

What's Changed

⚠️ Minimum Compatible Runner Version

v2.327.1
Release Notes

Make sure your runner is updated to this version or newer to use this release.

Full Changelog: https://github.com/actions/checkout/compare/v4...v5.0.0

v4.3.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4...v4.3.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.2&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/docs.yaml | 2 +- .github/workflows/e2e-test-event-writer.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 14 +++++++------- .github/workflows/kapinger.yaml | 2 +- .github/workflows/markdownlint.yaml | 2 +- .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ .github/workflows/release-validation.yaml | 2 +- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- .github/workflows/trivy.yaml | 2 +- .github/workflows/update-hubble.yaml | 2 +- 18 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 48f54d664c..b65e4325ac 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository if: env.IS_NOT_MERGE_GROUP - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go if: env.IS_NOT_MERGE_GROUP uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index e24a15ecb6..ed22e8725f 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-node@v4 with: node-version: 20 diff --git a/.github/workflows/e2e-test-event-writer.yml b/.github/workflows/e2e-test-event-writer.yml index bd41d73b99..216d3f86a9 100644 --- a/.github/workflows/e2e-test-event-writer.yml +++ b/.github/workflows/e2e-test-event-writer.yml @@ -31,4 +31,4 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 43d7546aec..07dc67b29f 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -86,7 +86,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 2da5823fbe..879732c2eb 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -20,7 +20,7 @@ jobs: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index aaa54dad0e..08d4b49e2f 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - name: Set up Go @@ -35,7 +35,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - name: Set up Go diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 18dfc3e7c2..4c08c95db5 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -74,7 +74,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -126,7 +126,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -176,7 +176,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -225,7 +225,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -282,7 +282,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup QEMU uses: docker/setup-qemu-action@v3 @@ -310,7 +310,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 6a329412c0..227ce6b77e 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set outputs id: vars diff --git a/.github/workflows/markdownlint.yaml b/.github/workflows/markdownlint.yaml index d11291efaf..db68bd3eaa 100644 --- a/.github/workflows/markdownlint.yaml +++ b/.github/workflows/markdownlint.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: DavidAnson/markdownlint-cli2-action@v9 with: command: config diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index b5eb02ba6e..7711bd058c 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 6334078a04..32406ad16f 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -19,7 +19,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 5c0fc217ea..57a609cebd 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -116,7 +116,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -161,7 +161,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -204,7 +204,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: @@ -254,7 +254,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index 45f303f9c5..9aa41d5d4b 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 - name: Get latest tag id: get_latest_tag diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 509c1bc063..2afde205f8 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -68,7 +68,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 358368754b..8baa84f5f1 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -15,7 +15,7 @@ jobs: tofu_version: 1.8.3 - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 42c74c944b..8c7cb46073 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 806b9f223a..6bc7885b5f 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest # trivy only supports running on Linux steps: - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Get Tag run: | diff --git a/.github/workflows/update-hubble.yaml b/.github/workflows/update-hubble.yaml index dc65eb5083..006b662471 100644 --- a/.github/workflows/update-hubble.yaml +++ b/.github/workflows/update-hubble.yaml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Get latest Hubble version id: get_version From bd3a9479e7de7805d66b5c17f7b3ede811e8b61f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 19:44:51 -0400 Subject: [PATCH 119/448] deps: bump golang.org/x/sys from 0.34.0 to 0.35.0 (#1808) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.34.0 to 0.35.0.
Commits
  • 5b936e1 unix/linux: update to Linux kernel 6.16, Go to 1.24.5
  • 3a82703 unix: remove redundant xnu version check for {p}readv/{p}writev
  • 9920300 unix: add missing nft conntrack constants
  • ad4e0fc unix: remove redundant word in comment
  • 084ad87 unix: fix //sys decl after CL 548795
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sys&package-manager=go_modules&previous-version=0.34.0&new-version=0.35.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 81c4029366..66682448c8 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( golang.org/x/net v0.42.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.16.0 - golang.org/x/sys v0.34.0 + golang.org/x/sys v0.35.0 golang.org/x/term v0.33.0 // indirect google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 8f5a512a52..301f073503 100644 --- a/go.sum +++ b/go.sum @@ -1781,8 +1781,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From 15cb0598e516b37f76afc6e21b2319b754b3d4af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 09:32:16 -0400 Subject: [PATCH 120/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.85.1 to 1.87.0 (#1813) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.85.1 to 1.87.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.85.1&new-version=1.87.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 66682448c8..797135515a 100644 --- a/go.mod +++ b/go.mod @@ -48,14 +48,14 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.35.1 // indirect @@ -272,10 +272,10 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.37.1 + github.com/aws/aws-sdk-go-v2 v1.38.0 github.com/aws/aws-sdk-go-v2/config v1.30.2 github.com/aws/aws-sdk-go-v2/credentials v1.18.2 - github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1 + github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 301f073503..5028332cd2 100644 --- a/go.sum +++ b/go.sum @@ -244,8 +244,8 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.37.1 h1:SMUxeNz3Z6nqGsXv0JuJXc8w5YMtrQMuIBmDx//bBDY= -github.com/aws/aws-sdk-go-v2 v1.37.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= +github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU= +github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= github.com/aws/aws-sdk-go-v2/config v1.30.2 h1:YE1BmSc4fFYqFgN1mN8uzrtc7R9x+7oSWeX8ckoltAw= @@ -256,30 +256,30 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 h1:owmNBboeA0kHKDcdF8KiSXm github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1/go.mod h1:Bg1miN59SGxrZqlP8vJZSmXW+1N8Y1MjQDq1OfuNod8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1 h1:ksZXBYv80EFTcgc8OJO48aQ8XDWXIQL7gGasPeCoTzI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.1/go.mod h1:HSksQyyJETVZS7uM54cir0IgxttTD+8aEoJMPGepHBI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1 h1:+dn/xF/05utS7tUhjIcndbuaPjfll2LhbH1cCDGLYUQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.1/go.mod h1:hyAGz30LHdm5KBZDI58MXx5lDVZ5CUfvfTZvMu4HCZo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.1 h1:4HbnOGE9491a9zYJ9VpPh1ApgEq6ZlD4Kuv1PJenFpc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.1/go.mod h1:Z6QnHC6TmpJWUxAy8FI4JzA7rTwl6EIANkyK9OR5z5w= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 h1:ZV2XK2L3HBq9sCKQiQ/MdhZJppH/rH0vddEAamsHUIs= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3/go.mod h1:b9F9tk2HdHpbf3xbN7rUZcfmJI26N6NcJu/8OsBFI/0= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1 h1:ps3nrmBWdWwakZBydGX1CxeYFK80HsQ79JLMwm7Y4/c= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1/go.mod h1:bAdfrfxENre68Hh2swNaGEVuFYE74o0SaSCAlaG9E74= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 h1:ky79ysLMxhwk5rxJtS+ILd3Mc8kC5fhsLBrP27r6h4I= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1/go.mod h1:+2MmkvFvPYM1vsozBWduoLJUi5maxFk5B7KJFECujhY= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1 h1:MdVYlN5pcQu1t1OYx4Ajo3fKl1IEhzgdPQbYFCRjYS8= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1/go.mod h1:iikmNLrvHm2p4a3/4BPeix2S9P+nW8yM1IZW73x8bFA= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 h1:3ZKmesYBaFX33czDl6mbrcHb6jeheg6LqjJhQdefhsY= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3/go.mod h1:7ryVb78GLCnjq7cw45N6oUb9REl7/vNUwjvIqC5UgdY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 h1:ieRzyHXypu5ByllM7Sp4hC5f/1Fy5wqxqY0yB85hC7s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3/go.mod h1:O5ROz8jHiOAKAwx179v+7sHMhfobFVi6nZt8DEyiYoM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 h1:SE/e52dq9a05RuxzLcjT+S5ZpQobj3ie3UTaSf2NnZc= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3/go.mod h1:zkpvBTsR020VVr8TOrwK2TrUW9pOir28sH5ECHpnAfo= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1 h1:Hsqo8+dFxSdDvv9B2PgIx1AJAnDpqgS0znVI+R+MoGY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1/go.mod h1:8Q0TAPXD68Z8YqlcIGHs/UNIDHsxErV9H4dl4vJEpgw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 h1:egoDf+Geuuntmw79Mz6mk9gGmELCPzg5PFEABOHB+6Y= +github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0/go.mod h1:t9MDi29H+HDbkolTSQtbI0HP9DemAWQzUjmWC7LGMnE= github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 h1:uWaz3DoNK9MNhm7i6UGxqufwu3BEuJZm72WlpGwyVtY= github.com/aws/aws-sdk-go-v2/service/sso v1.26.1/go.mod h1:ILpVNjL0BO+Z3Mm0SbEeUoYS9e0eJWV1BxNppp0fcb8= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 h1:XdG6/o1/ZDmn3wJU5SRAejHaWgKS4zHv0jBamuKuS2k= From 0f8f861e9ff6a3fa210275011134b5bdc361a070 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 23:16:55 -0400 Subject: [PATCH 121/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.30.2 to 1.31.6 (#1858) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.30.2 to 1.31.6.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.30.2&new-version=1.31.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 24 ++++++++++++------------ go.sum | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 797135515a..18f4887a85 100644 --- a/go.mod +++ b/go.mod @@ -47,19 +47,19 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.35.1 // indirect - github.com/aws/smithy-go v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 // indirect + github.com/aws/smithy-go v1.23.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -272,9 +272,9 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.38.0 - github.com/aws/aws-sdk-go-v2/config v1.30.2 - github.com/aws/aws-sdk-go-v2/credentials v1.18.2 + github.com/aws/aws-sdk-go-v2 v1.38.3 + github.com/aws/aws-sdk-go-v2/config v1.31.6 + github.com/aws/aws-sdk-go-v2/credentials v1.18.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 diff --git a/go.sum b/go.sum index 5028332cd2..5fd2e44176 100644 --- a/go.sum +++ b/go.sum @@ -244,22 +244,22 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU= -github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= +github.com/aws/aws-sdk-go-v2 v1.38.3 h1:B6cV4oxnMs45fql4yRH+/Po/YU+597zgWqvDpYMturk= +github.com/aws/aws-sdk-go-v2 v1.38.3/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= -github.com/aws/aws-sdk-go-v2/config v1.30.2 h1:YE1BmSc4fFYqFgN1mN8uzrtc7R9x+7oSWeX8ckoltAw= -github.com/aws/aws-sdk-go-v2/config v1.30.2/go.mod h1:UNrLGZ6jfAVjgVJpkIxjLufRJqTXCVYOpkeVf83kwBo= -github.com/aws/aws-sdk-go-v2/credentials v1.18.2 h1:mfm0GKY/PHLhs7KO0sUaOtFnIQ15Qqxt+wXbO/5fIfs= -github.com/aws/aws-sdk-go-v2/credentials v1.18.2/go.mod h1:v0SdJX6ayPeZFQxgXUKw5RhLpAoZUuynxWDfh8+Eknc= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1 h1:owmNBboeA0kHKDcdF8KiSXmrIuXZustfMGGytv6OMkM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.1/go.mod h1:Bg1miN59SGxrZqlP8vJZSmXW+1N8Y1MjQDq1OfuNod8= +github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= +github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ= +github.com/aws/aws-sdk-go-v2/credentials v1.18.10 h1:xdJnXCouCx8Y0NncgoptztUocIYLKeQxrCgN6x9sdhg= +github.com/aws/aws-sdk-go-v2/credentials v1.18.10/go.mod h1:7tQk08ntj914F/5i9jC4+2HQTAuJirq7m1vZVIhEkWs= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 h1:wbjnrrMnKew78/juW7I2BtKQwa1qlf6EjQgS69uYY14= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6/go.mod h1:AtiqqNrDioJXuUgz3+3T0mBWN7Hro2n9wll2zRUc0ww= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 h1:uF68eJA6+S9iVr9WgX1NaRGyQ/6MdIyc4JNUo6TN1FA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6/go.mod h1:qlPeVZCGPiobx8wb1ft0GHT5l+dc6ldnwInDFaMvC7Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 h1:pa1DEC6JoI0zduhZePp3zmhWvk/xxm4NB8Hy/Tlsgos= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6/go.mod h1:gxEjPebnhWGJoaDdtDkA0JX46VRg1wcTHYe63OfX5pE= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 h1:ZV2XK2L3HBq9sCKQiQ/MdhZJppH/rH0vddEAamsHUIs= @@ -268,26 +268,26 @@ github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7H github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 h1:3ZKmesYBaFX33czDl6mbrcHb6jeheg6LqjJhQdefhsY= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3/go.mod h1:7ryVb78GLCnjq7cw45N6oUb9REl7/vNUwjvIqC5UgdY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 h1:ieRzyHXypu5ByllM7Sp4hC5f/1Fy5wqxqY0yB85hC7s= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3/go.mod h1:O5ROz8jHiOAKAwx179v+7sHMhfobFVi6nZt8DEyiYoM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 h1:LHS1YAIJXJ4K9zS+1d/xa9JAA9sL2QyXIQCQFQW/X08= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6/go.mod h1:c9PCiTEuh0wQID5/KqA32J+HAgZxN9tOGXKCiYJjTZI= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 h1:SE/e52dq9a05RuxzLcjT+S5ZpQobj3ie3UTaSf2NnZc= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3/go.mod h1:zkpvBTsR020VVr8TOrwK2TrUW9pOir28sH5ECHpnAfo= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 h1:egoDf+Geuuntmw79Mz6mk9gGmELCPzg5PFEABOHB+6Y= github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0/go.mod h1:t9MDi29H+HDbkolTSQtbI0HP9DemAWQzUjmWC7LGMnE= -github.com/aws/aws-sdk-go-v2/service/sso v1.26.1 h1:uWaz3DoNK9MNhm7i6UGxqufwu3BEuJZm72WlpGwyVtY= -github.com/aws/aws-sdk-go-v2/service/sso v1.26.1/go.mod h1:ILpVNjL0BO+Z3Mm0SbEeUoYS9e0eJWV1BxNppp0fcb8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1 h1:XdG6/o1/ZDmn3wJU5SRAejHaWgKS4zHv0jBamuKuS2k= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.31.1/go.mod h1:oiotGTKadCOCl3vg/tYh4k45JlDF81Ka8rdumNhEnIQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.35.1 h1:iF4Xxkc0H9c/K2dS0zZw3SCkj0Z7n6AMnUiiyoJND+I= -github.com/aws/aws-sdk-go-v2/service/sts v1.35.1/go.mod h1:0bxIatfN0aLq4mjoLDeBpOjOke68OsFlXPDFJ7V0MYw= -github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= -github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 h1:8OLZnVJPvjnrxEwHFg9hVUof/P4sibH+Ea4KKuqAGSg= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.1/go.mod h1:27M3BpVi0C02UiQh1w9nsBEit6pLhlaH3NHna6WUbDE= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 h1:gKWSTnqudpo8dAxqBqZnDoDWCiEh/40FziUjr/mo6uA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2/go.mod h1:x7+rkNmRoEN1U13A6JE2fXne9EWyJy54o3n6d4mGaXQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 h1:YZPjhyaGzhDQEvsffDEcpycq49nl7fiGcfJTIo8BszI= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.2/go.mod h1:2dIN8qhQfv37BdUYGgEC8Q3tteM3zFxTI1MLO2O3J3c= +github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE= +github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f/go.mod h1:rAE739ssmE5O5fLuQ2y8uHdmOJaelE5I0Es3SxV0y1A= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From 6d1dfbf481d7809d1b1c43e8e7acb9ade94bd9e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:02:25 -0400 Subject: [PATCH 122/448] deps: bump actions/upload-pages-artifact from 3 to 4 (#1838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 3 to 4.
Release notes

Sourced from actions/upload-pages-artifact's releases.

v4.0.0

What's Changed

Full Changelog: https://github.com/actions/upload-pages-artifact/compare/v3.0.1...v4.0.0

v3.0.1

Changelog

See details of all code changes since previous release.

Commits
  • 7b1f4a7 Merge pull request #127 from heavymachinery/pin-sha
  • 4cc19c7 Pin actions/upload-artifact to SHA
  • 2d163be Merge pull request #107 from KittyChiu/main
  • c704843 fix: linted README
  • 9605915 Merge pull request #106 from KittyChiu/kittychiu/update-readme-1
  • e59cdfe Update README.md
  • a2d6704 doc: updated usage section in readme
  • 984864e Merge pull request #105 from actions/Jcambass-patch-1
  • 45dc788 Add workflow file for publishing releases to immutable action package
  • efaad07 Merge pull request #102 from actions/hidden-files
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-pages-artifact&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index ed22e8725f..ef400503ad 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -29,7 +29,7 @@ jobs: npm run build --prefix site/ - name: Upload build artifact if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 with: path: "./site/build" From a7c641d7c6dc19ab3be54eb58467864dbaa58cfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 10:58:33 -0400 Subject: [PATCH 123/448] deps: bump github.com/spf13/cobra from 1.9.1 to 1.10.1 (#1860) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.9.1 to 1.10.1.
Release notes

Sourced from github.com/spf13/cobra's releases.

v1.10.1

🐛 Fix

v1.0.9 of pflags brought back ParseErrorsWhitelist and marked it as deprecated

Full Changelog: https://github.com/spf13/cobra/compare/v1.10.0...v1.10.1

v1.10.0

What's Changed

🚨 Attention!

This version of pflag carried a breaking change: it renamed ParseErrorsWhitelist to ParseErrorsAllowlist which can break builds if both pflag and cobra are dependencies in your project.

  • If you use both pflag and cobra, upgrade pflagto 1.0.8 andcobrato1.10.0`
  • or use the newer, fixed version of pflag v1.0.9 which keeps the deprecated ParseErrorsWhitelist

More details can be found here: spf13/cobra#2303

✨ Features

🐛 Fix

🪠 Testing

📝 Docs

New Contributors

... (truncated)

Commits
  • 7da941c chore: Bump pflag to v1.0.9 (#2305)
  • 51d6751 Bump pflag to 1.0.8 (#2303)
  • 3f3b818 Update README.md with new logo
  • dcaf42e Add Periscope to the list of projects using Cobra (#2299)
  • 6dec1ae The default ShellCompDirective can be customized for a command and its subcom...
  • c8289c1 chore(golangci-lint): add some exclusion presets
  • 4af7b64 refactor: apply golangci-lint autofixes, work around false positives
  • 75790e4 chore(golangci-lint): upgrade to v2
  • db3ddb5 Adding sponsorship to README.md
  • 67171d6 putting sponsorship below header
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/spf13/cobra&package-manager=go_modules&previous-version=1.9.1&new-version=1.10.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 18f4887a85..aa8ffd7a76 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-chi/chi/v5 v5.2.2 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.23.0 - github.com/spf13/cobra v1.9.1 + github.com/spf13/cobra v1.10.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6 @@ -237,7 +237,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/spf13/pflag v1.0.7 + github.com/spf13/pflag v1.0.9 github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.42.0 // indirect diff --git a/go.sum b/go.sum index 5fd2e44176..a0a115590c 100644 --- a/go.sum +++ b/go.sum @@ -1373,12 +1373,11 @@ github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= -github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= From 6f676d4da0575b3b85695541d651ecd977f43534 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 11:59:31 -0400 Subject: [PATCH 124/448] deps: bump actions/setup-go from 5.5.0 to 6.0.0 (#1861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.5.0 to 6.0.0.
Release notes

Sourced from actions/setup-go's releases.

v6.0.0

What's Changed

Breaking Changes

Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. See Release Notes

Dependency Upgrades

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v5...v6.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=5.5.0&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 12 ++++++------ .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-images.yaml | 10 +++++----- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index b65e4325ac..41a9be2764 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go if: env.IS_NOT_MERGE_GROUP - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - name: Initialize CodeQL diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 07dc67b29f..57f7e8d33e 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -89,7 +89,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 879732c2eb..c5aeca76bd 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,7 +24,7 @@ jobs: if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 if: env.IS_NOT_MERGE_GROUP with: go-version-file: go.mod diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 08d4b49e2f..32b87c19e1 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -18,7 +18,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - name: Run GoReleaser build @@ -39,7 +39,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - name: Run GoReleaser release diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 4c08c95db5..f046f7ee47 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -25,7 +25,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -76,7 +76,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -128,7 +128,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -178,7 +178,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -227,7 +227,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -313,7 +313,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index 7711bd058c..9526be45c6 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -51,7 +51,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 57a609cebd..4b81b789b0 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -26,7 +26,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -72,7 +72,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -118,7 +118,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -163,7 +163,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version @@ -206,7 +206,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 2afde205f8..8405dea778 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -71,7 +71,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 8baa84f5f1..ef868d6271 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8c7cb46073..a6e88312eb 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod From 2ccc35592aadaf95e8bca74fa0f99664d70834fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 13:16:33 -0400 Subject: [PATCH 125/448] deps: bump actions/setup-node from 4 to 5 (#1862) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 5.
Release notes

Sourced from actions/setup-node's releases.

v5.0.0

What's Changed

Breaking Changes

Make sure your runner is updated to this version or newer to use this release. v2.327.1 Release Notes

Dependency Upgrades

Enhancement:

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v4...v5.0.0

v4.4.0

What's Changed

Bug fixes:

Enhancement:

Dependency update:

New Contributors

Full Changeloghttps://github.com/actions/setup-node/compare/v4...v4.4.0

v4.3.0

What's Changed

Dependency updates

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index ef400503ad..6f04ba3755 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 20 - name: build From f7bd5323394d3699c7490e58bf7080b26288c05e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 19:09:08 -0400 Subject: [PATCH 126/448] deps: bump aquasecurity/trivy-action from 0.32.0 to 0.33.1 (#1863) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.32.0 to 0.33.1.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.33.1

What's Changed

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.33.0...0.33.1

v0.33.0

What's Changed

New Contributors

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.32.0...0.33.0

Commits
  • b6643a2 Update setup-trivy action to version v0.2.4 (#486)
  • f9424c1 Merge pull request #481 from aquasecurity/bump-trivy-1755898251
  • 85abccb dev: delete fanal.db before tests
  • a169870 ci: update golden files on Trivy bump
  • 71f6a8f dev: add update-golden goal
  • bf330b1 test: update golden files
  • 644762e Merge pull request #482 from aquasecurity/fix-gh-actions
  • f2e2851 chore(ci): Add oras to correctly setup sync jobs
  • 636fd3c fix: update tests
  • 7c0244b chore(deps): Update trivy to v0.65.0
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.32.0&new-version=0.33.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 6bc7885b5f..c52adebe6c 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -30,7 +30,7 @@ jobs: echo "TAG=$(make version)" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From fcda5f1cd389ec51d431ad09619efd90d1af2bb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 19:09:27 -0400 Subject: [PATCH 127/448] chore(deps): bump github.com/ulikunitz/xz from 0.5.10 to 0.5.14 in /test/multicloud/test in the go_modules group across 1 directory (#1850) Bumps the go_modules group with 1 update in the /test/multicloud/test directory: [github.com/ulikunitz/xz](https://github.com/ulikunitz/xz). Updates `github.com/ulikunitz/xz` from 0.5.10 to 0.5.14
Commits
  • 7184815 Preparation of release v0.5.14
  • 88ddf1d Address Security Issue GHSA-jc7w-c686-c4v9
  • c8314b8 Add new package xio with WriteCloserStack
  • 4f11dce Update README.md and SECURITY.md to address security questions
  • f56ebbf TODO.md: fix a typo
  • 9d122a6 release version v0.5.11
  • 4ce6f08 lzma: fix handling of small dictionary sizes
  • 0b7c695 xz: add reader benchmark
  • 5535077 xz: add compression reate to Writer benchmark
  • 886dc9a xz: add benchmark for Writer
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/ulikunitz/xz&package-manager=go_modules&previous-version=0.5.10&new-version=0.5.14)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/multicloud/test/go.mod | 2 +- test/multicloud/test/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/multicloud/test/go.mod b/test/multicloud/test/go.mod index 68c50cc8ec..036b464491 100644 --- a/test/multicloud/test/go.mod +++ b/test/multicloud/test/go.mod @@ -50,7 +50,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/tmccombs/hcl2json v0.6.4 // indirect - github.com/ulikunitz/xz v0.5.10 // indirect + github.com/ulikunitz/xz v0.5.14 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zclconf/go-cty v1.15.0 // indirect golang.org/x/crypto v0.36.0 // indirect diff --git a/test/multicloud/test/go.sum b/test/multicloud/test/go.sum index 3e1d421d91..3ae36de007 100644 --- a/test/multicloud/test/go.sum +++ b/test/multicloud/test/go.sum @@ -119,8 +119,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw= github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= +github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From 748b45f8b94b31ec22de5ced0968eb785566c9d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 23:10:19 +0000 Subject: [PATCH 128/448] deps: bump azure/setup-helm from 4.3.0 to 4.3.1 (#1825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [azure/setup-helm](https://github.com/azure/setup-helm) from 4.3.0 to 4.3.1.
Release notes

Sourced from azure/setup-helm's releases.

v4.3.1

Changed

Added

Changelog

Sourced from azure/setup-helm's changelog.

[4.3.1] - 2025-08-12

Changed

Added

Commits
  • 1a275c3 build
  • 9e7f762 chore(release): v4.3.1 (#208)
  • c096176 Bump @​types/node from 24.1.0 to 24.2.1 in the actions group (#206)
  • 5e72872 ci(workflows): update helm version to v3.18.4 and add matrix for tests (#207)
  • fb8fa40 Update default helm version to 3.18.3 (#194)
  • 0d09729 chore: remove unnecessary prebuild script (#192)
  • 32bc120 chore(tests): Mock arch to make tests pass on arm host (#191)
  • 51463d6 Bump the actions group with 2 updates (#205)
  • aff1094 Bump the actions group across 1 directory with 2 updates (#204)
  • a10a524 Update helm version retrieval to use JSON output for latest version (#203)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azure/setup-helm&package-manager=github_actions&previous-version=4.3.0&new-version=4.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 32406ad16f..f94d99f6d8 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -23,7 +23,7 @@ jobs: with: fetch-depth: 0 - - uses: azure/setup-helm@v4.3.0 + - uses: azure/setup-helm@v4.3.1 id: install - name: Install Cosign From 567f4448d7f5c95e4ad7ba81445bea748d79eeff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 21:57:10 -0400 Subject: [PATCH 129/448] deps: bump google.golang.org/protobuf from 1.36.6 to 1.36.8 (#1827) Bumps google.golang.org/protobuf from 1.36.6 to 1.36.8. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/protobuf&package-manager=go_modules&previous-version=1.36.6&new-version=1.36.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aa8ffd7a76..1098ce1bdf 100644 --- a/go.mod +++ b/go.mod @@ -245,7 +245,7 @@ require ( golang.org/x/sync v0.16.0 golang.org/x/sys v0.35.0 golang.org/x/term v0.33.0 // indirect - google.golang.org/protobuf v1.36.6 + google.golang.org/protobuf v1.36.8 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 k8s.io/apimachinery v0.32.4 diff --git a/go.sum b/go.sum index a0a115590c..0c468f74c5 100644 --- a/go.sum +++ b/go.sum @@ -1888,8 +1888,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= From 5888e33462f3c734b84aa13661f5dc6c84d51c08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 01:57:49 +0000 Subject: [PATCH 130/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.10.1 to 1.11.0 (#1815) Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.10.1 to 1.11.0.
Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/azidentity's releases.

sdk/azidentity/v1.11.0

1.11.0 (2025-08-05)

Other Changes

  • DefaultAzureCredential tries its next credential when a dev tool credential such as AzureCLICredential returns an error

sdk/azidentity/v1.11.0-beta.1

1.11.0-beta.1 (2025-07-15)

Features Added

  • DefaultAzureCredential allows selecting one of its credential types by name via environment variable AZURE_TOKEN_CREDENTIALS. It will use only the selected type at runtime. For example, set AZURE_TOKEN_CREDENTIALS=WorkloadIdentityCredential to have DefaultAzureCredential use only WorkloadIdentityCredential.

Other Changes

  • By default, ManagedIdentityCredential retries IMDS requests for a maximum of ~70 seconds as recommended in IMDS documentation. In previous versions, it would stop retrying after ~54 seconds by default.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/azidentity&package-manager=go_modules&previous-version=1.10.1&new-version=1.11.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 5 +++-- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 1098ce1bdf..15cb2bda82 100644 --- a/go.mod +++ b/go.mod @@ -117,7 +117,7 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/golang-jwt/jwt/v5 v5.2.3 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.9 // indirect @@ -261,7 +261,7 @@ require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 @@ -575,6 +575,7 @@ require ( github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/raeperd/recvcheck v0.2.0 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 // indirect + github.com/redis/go-redis/v9 v9.7.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/ryancurrah/gomodguard v1.3.5 // indirect diff --git a/go.sum b/go.sum index 0c468f74c5..2e71e84518 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 h1:MhRfI58HblXzCtWEZCO0feHs8LweePB3s90r7WaR1KU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0/go.mod h1:okZ+ZURbArNdlJ+ptXoyHNuOETzOl1Oww19rm8I2WLA= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= @@ -688,8 +688,8 @@ github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= -github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= @@ -1283,8 +1283,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1 h1:+o7rrBoj54t8fqQSmnwRLdLzp5 github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1/go.mod h1:bWIjbxmrAk9eKGg9LSko3oQefoYGyWV4xzNS55PgL60= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 h1:LJF39lvUagUpKfL2/gZIp5vHv3AwXt9zOZ/Xual/CzI= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1/go.mod h1:VAY1vDpD/dLwfw/wU5SsexXNhCO9DjhRoGkmJeFONoE= -github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= -github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc= +github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= From 5637f75ea679245a356f6d8ed599f0b90df8774b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 09:57:16 -0400 Subject: [PATCH 131/448] deps: bump github.com/safchain/ethtool from 0.6.1 to 0.6.2 (#1821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/safchain/ethtool](https://github.com/safchain/ethtool) from 0.6.1 to 0.6.2.
Release notes

Sourced from github.com/safchain/ethtool's releases.

v0.6.2

What's Changed

New Contributors

Full Changelog: https://github.com/safchain/ethtool/compare/v0.6.1...v0.6.2

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/safchain/ethtool&package-manager=go_modules&previous-version=0.6.1&new-version=0.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 15cb2bda82..ba28e69260 100644 --- a/go.mod +++ b/go.mod @@ -297,7 +297,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.65.0 - github.com/safchain/ethtool v0.6.1 + github.com/safchain/ethtool v0.6.2 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 diff --git a/go.sum b/go.sum index 2e71e84518..aee3850475 100644 --- a/go.sum +++ b/go.sum @@ -1305,8 +1305,8 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a h1:np2nR32/A/VcOG9Hn+IOPA8kMk1gbBzK5LpSsgq5pJI= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a/go.mod h1:wiP6GQ2T378F+YIyuNw7yXtBxJZR+fqrrn1Z6UHZi0Q= -github.com/safchain/ethtool v0.6.1 h1:mhRnXE1H8fV8TTXh/HdqE4tXtb57r//BQh5pPYMuM5k= -github.com/safchain/ethtool v0.6.1/go.mod h1:JzoNbG8xeg/BeVeVoMCtCb3UPWoppZZbFpA+1WFh+M0= +github.com/safchain/ethtool v0.6.2 h1:O3ZPFAKEUEfbtE6J/feEe2Ft7dIJ2Sy8t4SdMRiIMHY= +github.com/safchain/ethtool v0.6.2/go.mod h1:VS7cn+bP3Px3rIq55xImBiZGHVLNyBh5dqG6dDQy8+I= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= From ba3200508cdae8e3af03eebf3945a0c25896665d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 09:57:30 -0400 Subject: [PATCH 132/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.87.0 to 1.87.3 (#1866) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.87.0 to 1.87.3.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.87.0&new-version=1.87.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index ba28e69260..ae1adeef22 100644 --- a/go.mod +++ b/go.mod @@ -46,16 +46,16 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 // indirect @@ -275,7 +275,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.38.3 github.com/aws/aws-sdk-go-v2/config v1.31.6 github.com/aws/aws-sdk-go-v2/credentials v1.18.10 - github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index aee3850475..9e3bbfb264 100644 --- a/go.sum +++ b/go.sum @@ -246,8 +246,8 @@ github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.38.3 h1:B6cV4oxnMs45fql4yRH+/Po/YU+597zgWqvDpYMturk= github.com/aws/aws-sdk-go-v2 v1.38.3/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00= github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ= github.com/aws/aws-sdk-go-v2/credentials v1.18.10 h1:xdJnXCouCx8Y0NncgoptztUocIYLKeQxrCgN6x9sdhg= @@ -262,24 +262,24 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 h1:pa1DEC6JoI0zduhZePp github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6/go.mod h1:gxEjPebnhWGJoaDdtDkA0JX46VRg1wcTHYe63OfX5pE= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 h1:ZV2XK2L3HBq9sCKQiQ/MdhZJppH/rH0vddEAamsHUIs= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3/go.mod h1:b9F9tk2HdHpbf3xbN7rUZcfmJI26N6NcJu/8OsBFI/0= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 h1:R0tNFJqfjHL3900cqhXuwQ+1K4G0xc9Yf8EDbFXCKEw= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6/go.mod h1:y/7sDdu+aJvPtGXr4xYosdpq9a6T9Z0jkXfugmti0rI= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 h1:3ZKmesYBaFX33czDl6mbrcHb6jeheg6LqjJhQdefhsY= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3/go.mod h1:7ryVb78GLCnjq7cw45N6oUb9REl7/vNUwjvIqC5UgdY= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 h1:hncKj/4gR+TPauZgTAsxOxNcvBayhUlYZ6LO/BYiQ30= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6/go.mod h1:OiIh45tp6HdJDDJGnja0mw8ihQGz3VGrUflLqSL0SmM= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 h1:LHS1YAIJXJ4K9zS+1d/xa9JAA9sL2QyXIQCQFQW/X08= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6/go.mod h1:c9PCiTEuh0wQID5/KqA32J+HAgZxN9tOGXKCiYJjTZI= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 h1:SE/e52dq9a05RuxzLcjT+S5ZpQobj3ie3UTaSf2NnZc= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3/go.mod h1:zkpvBTsR020VVr8TOrwK2TrUW9pOir28sH5ECHpnAfo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 h1:nEXUSAwyUfLTgnc9cxlDWy637qsq4UWwp3sNAfl0Z3Y= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6/go.mod h1:HGzIULx4Ge3Do2V0FaiYKcyKzOqwrhUZgCI77NisswQ= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 h1:egoDf+Geuuntmw79Mz6mk9gGmELCPzg5PFEABOHB+6Y= -github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0/go.mod h1:t9MDi29H+HDbkolTSQtbI0HP9DemAWQzUjmWC7LGMnE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 h1:ETkfWcXP2KNPLecaDa++5bsQhCRa5M5sLUJa5DWYIIg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3/go.mod h1:+/3ZTqoYb3Ur7DObD00tarKMLMuKg8iqz5CHEanqTnw= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 h1:8OLZnVJPvjnrxEwHFg9hVUof/P4sibH+Ea4KKuqAGSg= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1/go.mod h1:27M3BpVi0C02UiQh1w9nsBEit6pLhlaH3NHna6WUbDE= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 h1:gKWSTnqudpo8dAxqBqZnDoDWCiEh/40FziUjr/mo6uA= From 886904cbb6937cd82efbbdb55314497513eff9aa Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Tue, 16 Sep 2025 16:22:23 +0100 Subject: [PATCH 133/448] deps(tls-cve): Upgrade Windows to latest version (#1881) # Description Please provide a brief description of the changes made in this pull request. This pull request updates the Windows base images used in several Dockerfiles across the project to newer versions, ensuring that the builds use the latest security patches and improvements. No other functional or code changes are included. Updates to Windows base images: * Updated the `servercore:ltsc2019` image to digest [Copilot is generating a summary...]`dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9` in `controller/Dockerfile`, `controller/Dockerfile.windows-2019`, and `controller/Dockerfile.windows-retina-oss-build`. [[1]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L15-R18) [[2]](diffhunk://#diff-1ca5f5c74f2ae2779bc17c72c3b9e4eea6c410dee21dd74117fef13f7611980cL20-R20) [[3]](diffhunk://#diff-33c1aa48dbfaf078ee6f3be38eae828aa8b320d3ec28621e497611019210027fL6-R9) * Updated the `servercore:ltsc2022` image to digest `92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2` in `controller/Dockerfile`, `controller/Dockerfile.windows-2022`, and `controller/Dockerfile.windows-retina-oss-build`. [[1]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L15-R18) [[2]](diffhunk://#diff-7a317aaf2c0c39b0de61c4caa9ea7320062bae56d464e644eaeb3cd05e17b184L19-R19) [[3]](diffhunk://#diff-33c1aa48dbfaf078ee6f3be38eae828aa8b320d3ec28621e497611019210027fL6-R9) * Updated the `nanoserver:ltsc2019` image to digest `ea1b43fa8972684a5a284a6f441f91991fa7545d6912d2aecbf6c5ba60e73155` in `operator/Dockerfile.windows-2019`. * Updated the `nanoserver:ltsc2022` image to digest `580b7fa4040be7b47d79c25fb73e3d6da2e68f32b95d9d4dfb70bde33564fc4a` in `operator/Dockerfile.windows-2022` and `controller/Dockerfile.windows-native`. [[1]](diffhunk://#diff-bc2ff77ba131a806e5fddea1973783d61fdba4e8a33f307a982dca3b29b3956bL19-R19) [[2]](diffhunk://#diff-909d3861ff2ca17f232d98e86c2bcb422c49017732b04357a88210be028f7f17L27-R27)[Copilot is generating a summary...] ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Co-authored-by: Iti Agrawal --- controller/Dockerfile | 4 ++-- controller/Dockerfile.windows-2019 | 2 +- controller/Dockerfile.windows-2022 | 2 +- controller/Dockerfile.windows-native | 2 +- controller/Dockerfile.windows-retina-oss-build | 4 ++-- operator/Dockerfile.windows-2019 | 2 +- operator/Dockerfile.windows-2022 | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 1d431bd777..f0031ebddd 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -12,10 +12,10 @@ FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599a FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS azurelinux-distroless # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:2a7cfebaed9241227ad68b1fc7cb764867ea1c56624ece03f926eb8bdf0c998f AS ltsc2019 +FROM mcr.microsoft.com/windows/servercore@sha256:dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9 AS ltsc2019 # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:3281482945016cdaefbe417edd8338de8119e077b6941f74e78b050da1b7bd97 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2 AS ltsc2022 # build stages diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index bf1640611b..e6663eb943 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -17,7 +17,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/ca # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:2a7cfebaed9241227ad68b1fc7cb764867ea1c56624ece03f926eb8bdf0c998f as final +FROM mcr.microsoft.com/windows/servercore@sha256:dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9 as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 58da3c8b38..f1c21cb797 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/co RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:3281482945016cdaefbe417edd8338de8119e077b6941f74e78b050da1b7bd97 as final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2 as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index e52d870861..d62733e42e 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:9a57174ce85e979529e4f0cd58dff2e837b65fc7832b7585b4882f6cce0e255d AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:580b7fa4040be7b47d79c25fb73e3d6da2e68f32b95d9d4dfb70bde33564fc4a AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index 2e6c88ea90..73348bfede 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -3,10 +3,10 @@ ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:2a7cfebaed9241227ad68b1fc7cb764867ea1c56624ece03f926eb8bdf0c998f AS ltsc2019 +FROM mcr.microsoft.com/windows/servercore@sha256:dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9 AS ltsc2019 # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:3281482945016cdaefbe417edd8338de8119e077b6941f74e78b050da1b7bd97 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2 AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index 4cc6d24cf6..14857b1893 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:c357ed591af7b24f2d4a12b1947da5e6ebe559d89f41471f6928902c7cda7206 +FROM mcr.microsoft.com/windows/nanoserver@sha256:ea1b43fa8972684a5a284a6f441f91991fa7545d6912d2aecbf6c5ba60e73155 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 3b9feec346..3f53517685 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:9a57174ce85e979529e4f0cd58dff2e837b65fc7832b7585b4882f6cce0e255d +FROM mcr.microsoft.com/windows/nanoserver@sha256:580b7fa4040be7b47d79c25fb73e3d6da2e68f32b95d9d4dfb70bde33564fc4a COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 From fd113dd8bb68fc172a0a75f06a32e4e5116eb5d1 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Tue, 16 Sep 2025 18:57:12 +0100 Subject: [PATCH 134/448] deps(cve-2025-47907): update golang base images from 1.24.4 to 1.24.6 across multiple Dockerfiles (#1824) # Description Updated Go Lang version to mitigate cve-2025-47907 CVE-2025-47907 is a vulnerability in the Go programming language's database/sql package, discovered and disclosed on August 7, 2025. The vulnerability affects multiple versions of Go, specifically versions before 1.23.12 and from 1.24.0 before 1.24.6. This security issue was reported by Spike Curtis from Coder ([Go Project](https://pkg.go.dev/vuln/GO-2025-3849)). The issue has been fixed in Go versions 1.23.12 and 1.24.6. Users are advised to upgrade to these patched versions to mitigate the vulnerability ([Go Project](https://groups.google.com/g/golang-announce/c/x5MKroML2yM)). We are still waiting on hubble to bump their version with 1.24.6 golang version. image source; [CVE-2025-47907 Impact, Exploitability, and Mitigation Steps | Wiz](https://www.wiz.io/vulnerability-database/cve/cve-2025-47907) ## Checklist - [x ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x ] I have correctly attributed the author(s) of the code. - [x ] I have tested the changes locally. - [x ] I have followed the project's style guidelines. - [x ] I have updated the documentation, if necessary. - [x ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed This pull request upgrades the Go toolchain version used across all Dockerfiles and in the `go.mod` file from 1.24.4 (or 1.24.3 in `go.mod`) to 1.24.6. This ensures consistency and brings in the latest bug fixes and security updates from the Go project. **Go toolchain version upgrade:** * All Dockerfiles now use `mcr.microsoft.com/oss/go/microsoft/golang:1.24.6` (or the appropriate Windows variant) instead of `1.24.4`, updating the image digests and comments accordingly. [[1]](diffhunk://#diff-53fad39439c11209d1fd09c9c8dc733647e91161167f7daf14df477b78f06472L1-R2) [[2]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L5-R6) [[3]](diffhunk://#diff-49752700516c4cf7846baa53e3fcb9f628bff653b0364de4b273f9b900af954aL1-R2) [[4]](diffhunk://#diff-f0dd51cf34c442cdab8226a50e290ac00ab8276c9f8681dc4d8375ec07a8b3acL1-R2) [[5]](diffhunk://#diff-1ca5f5c74f2ae2779bc17c72c3b9e4eea6c410dee21dd74117fef13f7611980cL1-R2) [[6]](diffhunk://#diff-7a317aaf2c0c39b0de61c4caa9ea7320062bae56d464e644eaeb3cd05e17b184L1-R2) [[7]](diffhunk://#diff-1e96bef04d487cb2a4483d264828b723c73f33f3d8cd86facfd7b979b555b96cL1-R2) [[8]](diffhunk://#diff-909d3861ff2ca17f232d98e86c2bcb422c49017732b04357a88210be028f7f17L6-R7) [[9]](diffhunk://#diff-fb3f33cdd2a5865385222d244e9bdc9a7ebee2756d506f6495f83a5cff42b25aL1-R2) [[10]](diffhunk://#diff-0e1ebad4bf0d52c96d7d08447f373313b76ccb05384d36736eb6c1476744fb86L1-R2) [[11]](diffhunk://#diff-bc2ff77ba131a806e5fddea1973783d61fdba4e8a33f307a982dca3b29b3956bL1-R2) [[12]](diffhunk://#diff-105352849a03a69e1cb5f3d40e843034731e66737f833014a4589a6aeee29646L2-R3) [[13]](diffhunk://#diff-6a4f3c9e54acfa9ffd27a142ad70e1a7bb68c5d3d454366569fb2f148ac94993L1-R1) [[14]](diffhunk://#diff-0793df634d5904e90d444dade524fa1764c63179f1b3cca617f241a0e0711331L1-R1) * The `go.mod` file is updated to specify Go version 1.24.6 instead of 1.24.3.[Copilot is generating a summary...] ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/Dockerfile | 4 ++-- controller/Dockerfile | 4 ++-- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-2019 | 4 ++-- controller/Dockerfile.windows-2022 | 4 ++-- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 4 ++-- go.mod | 4 ++-- go.sum | 4 ++-- hack/tools/kapinger/Dockerfile | 2 +- hack/tools/toolbox/Dockerfile | 2 +- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2019 | 4 ++-- operator/Dockerfile.windows-2022 | 4 ++-- test/image/Dockerfile | 4 ++-- 16 files changed, 30 insertions(+), 30 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index e24332209c..4a59383145 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index f0031ebddd..7285a7653d 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -2,8 +2,8 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index a58e772765..9ccf8822b6 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 1d45efa488..e8d7f37da2 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index e6663eb943..1e26fec9b6 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder # Build args ARG VERSION diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index f1c21cb797..d3277af81c 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder # Build args ARG VERSION diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 002630d676..91a2398da3 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:f9c24af183306a0a2fa55601909601f347694573a14f03cd2afe9400d0fde01b AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:c5acaeb9bed15c7c3d7f5ed73d2b56c76ce5efa09e498bbb2e7f7f9a6d2559f2 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index d62733e42e..d5e7f37c21 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:f9c24af183306a0a2fa55601909601f347694573a14f03cd2afe9400d0fde01b AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:c5acaeb9bed15c7c3d7f5ed73d2b56c76ce5efa09e498bbb2e7f7f9a6d2559f2 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/go.mod b/go.mod index ae1adeef22..b285e73910 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/microsoft/retina -go 1.24.3 +go 1.24.6 require ( github.com/go-chi/chi/v5 v5.2.2 @@ -458,7 +458,7 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gofrs/flock v0.12.1 // indirect diff --git a/go.sum b/go.sum index 9e3bbfb264..538059bc51 100644 --- a/go.sum +++ b/go.sum @@ -663,8 +663,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +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/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 2593300fd3..d6661b957e 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.5 AS builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.6 AS builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 02a4bec438..f4c839736b 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.5 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.6 AS build ADD . . WORKDIR /go/toolbox/ RUN CGO_ENABLED=0 GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 03b6e8a1cc..4790b48505 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index 14857b1893..f201fa01f1 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder # Build args ARG VERSION diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 3f53517685..c8af57125f 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index c73331acda..57813ad0ea 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.5-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7f705f63001ad064018c1610455ae1c23e6c8179fbc6cc87bcd5d51d2c4760f6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder ENV CGO_ENABLED=0 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 1a3912380cd4f46193665cb8c5d19b73986adf50 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Mon, 22 Sep 2025 10:57:50 +0000 Subject: [PATCH 135/448] docs: Update retina shell documentation (#1854) # Description Updating the retina shell documentation to be more comprehensive. Removing the readme from `/shell` in favour of the documentation page to avoid having to maintain two documents. ## Related Issue https://github.com/microsoft/retina/issues/1835 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Kamil --- docs/06-Troubleshooting/shell.md | 144 ++++++++++++++++++++++++------- shell/README.md | 62 ------------- 2 files changed, 114 insertions(+), 92 deletions(-) delete mode 100644 shell/README.md diff --git a/docs/06-Troubleshooting/shell.md b/docs/06-Troubleshooting/shell.md index 3bf5adbb1d..284217993b 100644 --- a/docs/06-Troubleshooting/shell.md +++ b/docs/06-Troubleshooting/shell.md @@ -1,21 +1,37 @@ # Shell -**EXPERIMENTAL: `retina shell` is an experimental feature, so the flags and behavior may change in future versions.** +>NOTE: `retina shell` is an experimental feature. The flags and behavior may change in future versions. -The `retina shell` command allows you to start an interactive shell on a Kubernetes node or pod. This runs a container image with many common networking tools installed (`ping`, `curl`, etc.). +The `retina shell` command allows you to start an interactive shell on a Kubernetes node or pod for adhoc debugging. -## Testing connectivity +This runs a container image built from the Dockerfile in the `/shell` directory, with many common networking tools installed (`ping`, `curl`, etc.), as well as specialized tools such as [bpftool](#bpftool), [pwru](#pwru) or [Inspektor Gadget](#inspektor-gadget-ig). -Start a shell on a node or inside a pod +Currently the Retina Shell only works in Linux environments. Windows support will be added in the future. -```bash +## Getting Started + +Start a shell on a node or inside a pod: + +```shell # To start a shell in a node (root network namespace): -kubectl retina shell aks-nodepool1-15232018-vmss000001 +kubectl retina shell # To start a shell inside a pod (pod network namespace): -kubectl retina shell -n kube-system pods/coredns-d459997b4-7cpzx +kubectl retina shell -n kube-system pods/ + +# To start a shell inside of a node and mount the host file system +kubectl retina shell --mount-host-filesystem + +# To start a shell inside of a node with extra capabilities +kubectl retina shell --capabilities= ``` +For testing, you can override the image used by `retina shell` either with CLI arguments (`--retina-shell-image-repo` and `--retina-shell-image-version`) or environment variables (`RETINA_SHELL_IMAGE_REPO` and `RETINA_SHELL_IMAGE_VERSION`). + +Run `kubectl retina shell -h` for full documentation and examples. + +## Testing connectivity + Check connectivity using `ping`: ```text @@ -32,15 +48,6 @@ PING 10.224.0.4 (10.224.0.4) 56(84) bytes of data. rtt min/avg/max/mdev = 0.908/1.015/1.128/0.077 ms ``` -Check DNS resolution using `dig`: - -```text -root [ / ]# dig example.com +short -93.184.215.14 -``` - -The tools `nslookup` and `drill` are also available if you prefer those. - Check connectivity to apiserver using `nc` and `curl`: ```text @@ -61,12 +68,23 @@ root [ / ]# curl -k https://10.0.0.1 } ``` -### nftables and iptables +## DNS Resolution + +Check DNS resolution using `dig`: + +```text +root [ / ]# dig example.com +short +93.184.215.14 +``` + +The tools `nslookup` and `drill` are also available if you prefer those. + +## nftables and iptables Accessing nftables and iptables rules requires `NET_RAW` and `NET_ADMIN` capabilities. -```bash -kubectl retina shell aks-nodepool1-15232018-vmss000002 --capabilities NET_ADMIN,NET_RAW +```text +kubectl retina shell --capabilities NET_ADMIN,NET_RAW ``` Then you can run `iptables` and `nft`: @@ -74,13 +92,14 @@ Then you can run `iptables` and `nft`: ```text root [ / ]# iptables -nvL | head -n 2 Chain INPUT (policy ACCEPT 1191K packets, 346M bytes) - pkts bytes target prot opt in out source destination + pkts bytes target prot opt in out source destination + root [ / ]# nft list ruleset | head -n 2 # Warning: table ip filter is managed by iptables-nft, do not touch! table ip filter { ``` -**If you see the error "Operation not permitted (you must be root)", check that your `kubectl retina shell` command sets `--capabilities NET_RAW,NET_ADMIN`.** +>NOTE: If you see the error "Operation not permitted (you must be root)", check that your `kubectl retina shell` command sets `--capabilities NET_RAW,NET_ADMIN`. `iptables` in the shell image uses `iptables-nft`, which may or may not match the configuration on the node. For example, Azure Linux 2 maps `iptables` to `iptables-legacy`. To use the exact same `iptables` binary as installed on the node, you will need to `chroot` into the host filesystem (see below). @@ -88,8 +107,8 @@ table ip filter { On nodes, you can mount the host filesystem to `/host`: -```bash -kubectl retina shell aks-nodepool1-15232018-vmss000002 --mount-host-filesystem +```text +kubectl retina shell --mount-host-filesystem ``` This mounts the host filesystem (`/`) to `/host` in the debug pod: @@ -108,7 +127,7 @@ Symlinks between files on the host filesystem may not resolve correctly. If you `chroot` requires the `SYS_CHROOT` capability: ```bash -kubectl retina shell aks-nodepool1-15232018-vmss000002 --mount-host-filesystem --capabilities SYS_CHROOT +kubectl retina shell --mount-host-filesystem --capabilities SYS_CHROOT ``` Then you can use `chroot` to switch to start a shell inside the host filesystem: @@ -133,7 +152,7 @@ search shncgv2kgepuhm1ls1dwgholsd.cx.internal.cloudapp.net `systemctl` commands require both `chroot` to the host filesystem and host PID: ```bash -kubectl retina shell aks-nodepool1-15232018-vmss000002 --mount-host-filesystem --capabilities SYS_CHROOT --host-pid +kubectl retina shell --mount-host-filesystem --capabilities SYS_CHROOT --host-pid ``` Then `chroot` to the host filesystem and run `systemctl status`: @@ -144,7 +163,69 @@ root [ / ]# chroot /host systemctl status | head -n 2 State: running ``` -**If `systemctl` shows an error "Failed to connect to bus: No data available", check that the `retina shell` command has `--host-pid` set and that you have chroot'd to /host.** +>NOTE: If `systemctl` shows an error "Failed to connect to bus: No data available", check that the `retina shell` command has `--host-pid` set and that you have chroot'd to /host. + +## [pwru](https://github.com/cilium/pwru) + +eBPF-based tool for tracing network packets in the Linux kernel with advanced filtering capabilities. It allows fine-grained introspection of kernel state to facilitate debugging network connectivity issues. + +Requires the `NET_ADMIN` and `SYS_ADMIN` capabilities. + +Capability requirements are based on common eBPF tool practices and not directly from the pwru documentation. + +```shell +kubectl retina shell -n kube-system pod/ --capabilities=NET_ADMIN,SYS_ADMIN +``` + +You can then run, for example: + +```shell +pwru -h +pwru "tcp and (src port 8080 or dst port 8080)" +``` + +## [bpftool](https://github.com/libbpf/bpftool) + +Allows you to list, dump, load BPF programs, etc. Reference utility to quickly inspect and manage BPF objects on your system, to manipulate BPF object files, or to perform various other BPF-related tasks. + +Requires the `NET_ADMIN` and `SYS_ADMIN` capabilities. + +```shell +kubectl retina shell -n kube-system pod/ --capabilities=NET_ADMIN,SYS_ADMIN +``` + +You can then run for example: + +```shell +bpftool -h +bpftool prog show +bpftool map dump id +``` + +## [Inspektor Gadget (ig)](https://inspektor-gadget.io/) + +Tools and framework for data collection and system inspection on Kubernetes clusters and Linux hosts using eBPF. + +To use `ig`, you need to add the `--mount-host-filesystem`, `--apparmor-unconfined` and `--seccomp-unconfined` flags, along with the following capabilities: + +* `NET_ADMIN` +* `SYS_ADMIN` +* `SYS_RESOURCE` +* `SYSLOG` +* `IPC_LOCK` +* `SYS_PTRACE` +* `NET_RAW` + +```shell +kubectl retina shell --capabilities=NET_ADMIN,SYS_ADMIN,SYS_RESOURCE,SYSLOG,IPC_LOCK,SYS_PTRACE,NET_RAW --mount-host-filesystem --apparmor-unconfined --seccomp-unconfined +``` + +You can then run for example: + +```shell +ig -h +ig run trace_dns:latest +``` ## Troubleshooting @@ -158,7 +239,8 @@ If `kubectl retina shell` fails with a timeout error, then: Example: ```bash -kubectl retina shell --timeout 10m node001 # increase timeout to 10 minutes +# increase timeout to 10 minutes +kubectl retina shell --timeout 10m ``` ### Firewalls and ImagePullBackoff @@ -172,14 +254,16 @@ Example: ```bash export RETINA_SHELL_IMAGE_REPO="example.azurecr.io/retina/retina-shell" -export RETINA_SHELL_IMAGE_VERSION=v0.0.1 # optional, if not set defaults to the Retina CLI version. -kubectl retina shell node0001 # this will use the image "example.azurecr.io/retina/retina-shell:v0.0.1" +# optional, if not set defaults to the Retina CLI version. +export RETINA_SHELL_IMAGE_VERSION=v0.0.1 +# this will use the image "example.azurecr.io/retina/retina-shell:v0.0.1" +kubectl retina shell ``` ## Limitations * Windows nodes and pods are not yet supported. -* `bpftool` and `bpftrace` are not supported. +* `bpftrace` not yet supported. * The shell image links `iptables` commands to `iptables-nft`, even if the node itself links to `iptables-legacy`. * `nsenter` is not supported. * `ip netns` will not work without `chroot` to the host filesystem. diff --git a/shell/README.md b/shell/README.md deleted file mode 100644 index 14e6c3252d..0000000000 --- a/shell/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# retina-shell - -Retina CLI provides a command to launch an interactive shell in a node or pod for adhoc debugging. - -* The CLI command `kubectl retina shell` creates a pod with `HostNetwork=true` (for node debugging) or an ephemeral container in an existing pod (for pod debugging). -* The container runs an image built from the Dockerfile in this directory. The image is based on Azure Linux and includes commonly-used networking tools. -* The [pwru](https://github.com/cilium/pwru) tool is bundled in the image for advanced kernel packet tracing. -* bpftool is also included for eBPF debugging. -* [Inspektor Gadget (ig)](https://inspektor-gadget.io/) is included for additional debugging capabilities. - -For testing, you can override the image used by `retina shell` either with CLI arguments -(`--retina-shell-image-repo` and `--retina-shell-image-version`) or environment variables -(`RETINA_SHELL_IMAGE_REPO` and `RETINA_SHELL_IMAGE_VERSION`). - -Run `kubectl retina shell -h` for full documentation and examples. - -## Example: Running pwru and bpftool - -To use `pwru` and `bpftool` inside the retina shell, you must grant the following Linux capabilities to the container: - -* `NET_ADMIN` -* `SYS_ADMIN` - -Capability requirements are based on common eBPF tool practices and not directly from the pwru documentation. - -Example command to launch a shell with the required capabilities: - -```sh -# Pod debugging -kubectl retina shell -n kube-system pod/coredns-57d886c994-8m2ph --capabilities=NET_ADMIN,SYS_ADMIN -``` - -Once inside the shell, you can run: - -```sh -pwru --help -bpftool --help -``` - -To use `ig`, you need to add the `--mount-host-filesystem`, `--apparmor-unconfined` and `--seccomp-unconfined` flags, along with the following capabilities: - -* `NET_ADMIN` -* `SYS_ADMIN` -* `SYS_RESOURCE` -* `SYSLOG` -* `IPC_LOCK` -* `SYS_PTRACE` -* `NET_RAW` - -```sh -# Node debugging -kubectl retina shell aks-nodepool1-42816995-vmss000001 --capabilities=NET_ADMIN,SYS_ADMIN,SYS_RESOURCE,SYSLOG,IPC_LOCK,SYS_PTRACE,NET_RAW --mount-host-filesystem --apparmor-unconfined --seccomp-unconfined -``` - -Once inside the shell, you can run: - -```sh -ig -h -ig run trace_dns:latest -``` - -Currently only Linux is supported; Windows support will be added in the future. From 2369544986d5dbfeb1ff193bcdae85c75563691f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:54:14 -0700 Subject: [PATCH 136/448] deps: bump github.com/onsi/ginkgo/v2 from 2.23.4 to 2.25.3 (#1879) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.23.4 to 2.25.3.
Release notes

Sourced from github.com/onsi/ginkgo/v2's releases.

v2.25.3

2.25.3

Fixes

  • emit --github-output group only for progress report itself [f01aed1]

v2.25.2

2.25.2

Fixes

Add github output group for progress report content

Maintenance

Bump Gomega

v2.25.1

2.25.1

Fixes

  • fix(types): ignore nameless nodes on FullText() [10866d3]
  • chore: fix some CodeQL warnings [2e42cff]

v2.25.0

2.25.0

AroundNode

This release introduces a new decorator to support more complex spec setup usecases.

AroundNode registers a function that runs before each individual node. This is considered a more advanced decorator.

Please read the docs for more information and some examples.

Allowed signatures:

  • AroundNode(func()) - func will be called before the node is run.
  • AroundNode(func(ctx context.Context) context.Context) - func can wrap the passed in context and return a new one which will be passed on to the node.
  • AroundNode(func(ctx context.Context, body func(ctx context.Context))) - ctx is the context for the node and body is a function that must be called to run the node. This gives you complete control over what runs before and after the node.

Multiple AroundNode decorators can be applied to a single node and they will run in the order they are applied.

Unlike setup nodes like BeforeEach and DeferCleanup, AroundNode is guaranteed to run in the same goroutine as the decorated node. This is necessary when working with lower-level libraries that must run on a single thread (you can call runtime.LockOSThread() in the AroundNode to ensure that the node runs on a single thread).

Since AroundNode allows you to modify the context you can also use AroundNode to implement shared setup that attaches values to the context.

If applied to a container, AroundNode will run before every node in the container. Including setup nodes like BeforeEach and DeferCleanup.

AroundNode can also be applied to RunSpecs to run before every node in the suite. This opens up new mechanisms for instrumenting individual nodes across an entire suite.

... (truncated)

Changelog

Sourced from github.com/onsi/ginkgo/v2's changelog.

2.25.3

Fixes

  • emit --github-output group only for progress report itself [f01aed1]

2.25.2

Fixes

Add github output group for progress report content

Maintenance

Bump Gomega

2.25.1

Fixes

  • fix(types): ignore nameless nodes on FullText() [10866d3]
  • chore: fix some CodeQL warnings [2e42cff]

2.25.0

AroundNode

This release introduces a new decorator to support more complex spec setup usecases.

AroundNode registers a function that runs before each individual node. This is considered a more advanced decorator.

Please read the docs for more information and some examples.

Allowed signatures:

  • AroundNode(func()) - func will be called before the node is run.
  • AroundNode(func(ctx context.Context) context.Context) - func can wrap the passed in context and return a new one which will be passed on to the node.
  • AroundNode(func(ctx context.Context, body func(ctx context.Context))) - ctx is the context for the node and body is a function that must be called to run the node. This gives you complete control over what runs before and after the node.

Multiple AroundNode decorators can be applied to a single node and they will run in the order they are applied.

Unlike setup nodes like BeforeEach and DeferCleanup, AroundNode is guaranteed to run in the same goroutine as the decorated node. This is necessary when working with lower-level libraries that must run on a single thread (you can call runtime.LockOSThread() in the AroundNode to ensure that the node runs on a single thread).

Since AroundNode allows you to modify the context you can also use AroundNode to implement shared setup that attaches values to the context.

If applied to a container, AroundNode will run before every node in the container. Including setup nodes like BeforeEach and DeferCleanup.

AroundNode can also be applied to RunSpecs to run before every node in the suite. This opens up new mechanisms for instrumenting individual nodes across an entire suite.

2.24.0

Features

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/onsi/ginkgo/v2&package-manager=go_modules&previous-version=2.23.4&new-version=2.25.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 22 ++++++++++++---------- go.sum | 44 ++++++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index b285e73910..eded79cd27 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -209,11 +209,11 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/mod v0.25.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.34.0 // indirect + golang.org/x/tools v0.36.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect @@ -240,11 +240,11 @@ require ( github.com/spf13/pflag v1.0.9 github.com/stretchr/testify v1.10.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.42.0 // indirect + golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.16.0 golang.org/x/sys v0.35.0 - golang.org/x/term v0.33.0 // indirect + golang.org/x/term v0.34.0 // indirect google.golang.org/protobuf v1.36.8 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 @@ -292,8 +292,8 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.0 - github.com/onsi/ginkgo/v2 v2.23.4 - github.com/onsi/gomega v1.38.0 + github.com/onsi/ginkgo/v2 v2.25.3 + github.com/onsi/gomega v1.38.2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.65.0 @@ -641,9 +641,11 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - go.yaml.in/yaml/v3 v3.0.3 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect gocloud.dev v0.37.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect + golang.org/x/tools/go/expect v0.1.1-deprecated // indirect + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/api v0.223.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect diff --git a/go.sum b/go.sum index 538059bc51..e08d94c40a 100644 --- a/go.sum +++ b/go.sum @@ -175,8 +175,8 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +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/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= @@ -1185,14 +1185,14 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= -github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw= +github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= -github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= 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.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -1604,8 +1604,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= -go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= -go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= gocloud.dev v0.37.0 h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro= @@ -1627,8 +1627,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1655,8 +1655,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1696,8 +1696,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= @@ -1792,8 +1792,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1805,8 +1805,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1841,8 +1841,12 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= 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= From b0f09b1f45d8cab974f8b498ee40212134015075 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:24:20 +0100 Subject: [PATCH 137/448] chore(shell): Add mpstat and doc (#1889) # Description See title. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Screenshot 2025-09-26 153300 Screenshot 2025-09-26 152236 ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- docs/06-Troubleshooting/shell.md | 10 ++++++++++ shell/Dockerfile | 1 + 2 files changed, 11 insertions(+) diff --git a/docs/06-Troubleshooting/shell.md b/docs/06-Troubleshooting/shell.md index 284217993b..9f12bd95e4 100644 --- a/docs/06-Troubleshooting/shell.md +++ b/docs/06-Troubleshooting/shell.md @@ -227,6 +227,16 @@ ig -h ig run trace_dns:latest ``` +## [mpstat](https://www.man7.org/linux/man-pages/man1/mpstat.1.html) + +Tool for detailed reporting of processor-related statistics. `mpstat` is useful for network troubleshooting because it shows how much CPU time is spent handling SoftIRQs, which are often triggered by network traffic, helping identify interrupt bottlenecks or imbalanced CPU usage. SoftIRQs (Software Interrupt Requests) are a type of deferred interrupt handling mechanism in the Linux kernel used to process time-consuming tasks—like network packet handling or disk I/O—outside the immediate hardware interrupt context, allowing faster and more efficient interrupt processing without blocking the system. + +This example usage of `mpstat` monitors CPU usage statistics, specifically focusing on SoftIRQ usage, across all CPU cores, sampled every 1 second, for 5 intervals. + +```shell +mpstat -P ALL 1 5 | grep -E '(CPU|%soft|Average)' +``` + ## Troubleshooting ### Timeouts diff --git a/shell/Dockerfile b/shell/Dockerfile index 8642af0478..1374511d2e 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -20,6 +20,7 @@ RUN tdnf install -y \ nmap \ nmap-ncat \ openssh \ + sysstat \ socat \ tcpdump \ wget \ From 56c337ac65d63b9e53a79121c70ada2d47c5dd13 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:12:38 +0100 Subject: [PATCH 138/448] fix: Update busy box image for download pod (#1897) # Description Update image of busybox pod used for capture download. Testing steps - Create kind cluster - Install gatekeeper for policy inforcemente - Apply constraint that denies - Download a capture with the busybox docker image - check that it fails - Download a capture with the busybox mcr image - downloads without issues - Followed the same steps for an aks cluster and the mcr busybox as a sanity check ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/cmd/capture/download.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index ac3a0776e5..5c0a74322c 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -172,7 +172,7 @@ func createDownloadPod(ctx context.Context, kubeClient *kubernetes.Clientset, na Containers: []corev1.Container{ { Name: "download", - Image: "busybox", + Image: "mcr.microsoft.com/azurelinux/busybox:1.36", Command: []string{"sh", "-c", "echo 'Download pod ready'; sleep 3600"}, VolumeMounts: []corev1.VolumeMount{ { From 301dffdd63e93cb9980b49957f32e7849a8d78ed Mon Sep 17 00:00:00 2001 From: Artem <122204149+letv1nnn@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:44:25 +0100 Subject: [PATCH 139/448] docs: included instructions to docker login to access ghcr (#1891) # Description Added a note in the installation documentation to include instructions for authenticating to GitHub Container Registry, before installing Retina via Helm. This ensures users avoid credential errors when pulling images. (my first pr) ## Related Issue This pull request is related to #631 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: letv1nnn Signed-off-by: letv1nnn --- docs/02-Installation/01-Setup.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/02-Installation/01-Setup.md b/docs/02-Installation/01-Setup.md index b59d92efac..13c1751dd8 100644 --- a/docs/02-Installation/01-Setup.md +++ b/docs/02-Installation/01-Setup.md @@ -64,6 +64,10 @@ helm upgrade --install retina oci://ghcr.io/microsoft/retina/charts/retina \ ### Standard Control Plane +>NOTE: Before installing Retina via Helm, you need to authenticate to [GitHub Container Registry (GHCR)](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) to pull the required images. + +Run the following command: `docker login ghcr.io` + #### Basic Mode ```shell From f8f1db9adb4ff221c2e07b79028f9cd0128c1ef4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 12:23:51 -0400 Subject: [PATCH 140/448] deps: bump github/codeql-action from 3 to 4 (#1894) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
Release notes

Sourced from github/codeql-action's releases.

v3.30.7

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.7 - 06 Oct 2025

No user facing changes.

See the full CHANGELOG.md for more information.

v3.30.6

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.6 - 02 Oct 2025

  • Update default CodeQL bundle version to 2.23.2. #3168

See the full CHANGELOG.md for more information.

v3.30.5

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.5 - 26 Sep 2025

  • We fixed a bug that was introduced in 3.30.4 with upload-sarif which resulted in files without a .sarif extension not getting uploaded. #3160

See the full CHANGELOG.md for more information.

v3.30.4

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

3.30.4 - 25 Sep 2025

  • We have improved the CodeQL Action's ability to validate that the workflow it is used in does not use different versions of the CodeQL Action for different workflow steps. Mixing different versions of the CodeQL Action in the same workflow is unsupported and can lead to unpredictable results. A warning will now be emitted from the codeql-action/init step if different versions of the CodeQL Action are detected in the workflow file. Additionally, an error will now be thrown by the other CodeQL Action steps if they load a configuration file that was generated by a different version of the codeql-action/init step. #3099 and #3100
  • We added support for reducing the size of dependency caches for Java analyses, which will reduce cache usage and speed up workflows. This will be enabled automatically at a later time. #3107
  • You can now run the latest CodeQL nightly bundle by passing tools: nightly to the init action. In general, the nightly bundle is unstable and we only recommend running it when directed by GitHub staff. #3130
  • Update default CodeQL bundle version to 2.23.1. #3118

See the full CHANGELOG.md for more information.

v3.30.3

CodeQL Action Changelog

... (truncated)

Commits
  • aac66ec Remove update-proxy-release workflow
  • 91a63dc Remove undefined values from results of unsafeEntriesInvariant
  • d25fa60 ESLint: Disable no-unused-vars for parameters starting with _
  • 3adb1ff Reorder supported tags in descending order
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 41a9be2764..686846cb93 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -36,14 +36,14 @@ jobs: go-version-file: go.mod - name: Initialize CodeQL if: env.IS_NOT_MERGE_GROUP - uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 with: languages: ${{ matrix.language }} - name: Autobuild if: env.IS_NOT_MERGE_GROUP - uses: github/codeql-action/autobuild@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 - name: Perform CodeQL Analysis if: env.IS_NOT_MERGE_GROUP - uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index c52adebe6c..a82a292260 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -39,6 +39,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: "trivy-results.sarif" From 85936f6d7d808d9fabe12f36658f6eed4aa3f4d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 16:24:38 +0000 Subject: [PATCH 141/448] deps: bump golang.org/x/sync from 0.16.0 to 0.17.0 (#1869) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.16.0 to 0.17.0.
Commits
  • 04914c2 all: upgrade go directive to at least 1.24.0 [generated]
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sync&package-manager=go_modules&previous-version=0.16.0&new-version=0.17.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eded79cd27..ef42dd40e0 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 + golang.org/x/sync v0.17.0 golang.org/x/sys v0.35.0 golang.org/x/term v0.34.0 // indirect google.golang.org/protobuf v1.36.8 diff --git a/go.sum b/go.sum index e08d94c40a..f849c78814 100644 --- a/go.sum +++ b/go.sum @@ -1715,8 +1715,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 9a535b6d85e64c78c86a0dcf8b753ba1a3f106f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 18:33:50 -0400 Subject: [PATCH 142/448] deps: bump google.golang.org/grpc from 1.74.2 to 1.75.1 (#1873) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.74.2 to 1.75.1.
Release notes

Sourced from google.golang.org/grpc's releases.

Release 1.75.1

Bug Fixes

  • transport: Fix a data race while copying headers for stats handlers in the std lib http2 server transport. (#8519)
  • xdsclient:
    • Fix a data race caused while reporting load to LRS. (#8483)
    • Fix regression preventing empty node IDs when creating an LRS client. (#8483)
  • server: Fix a regression preventing streams from being cancelled or timed out when blocked on flow control. (#8528)

Release 1.75.0

Behavior Changes

  • xds: Remove support for GRPC_EXPERIMENTAL_XDS_FALLBACK environment variable. Fallback support can no longer be disabled. (#8482)
  • stats: Introduce DelayedPickComplete event, a type alias of PickerUpdated. (#8465)
    • This (combined) event will now be emitted only once per call, when a transport is successfully selected for the attempt.
    • OpenTelemetry metrics will no longer have multiple "Delayed LB pick complete" events in Go, matching other gRPC languages.
    • A future release will delete the PickerUpdated symbol.
  • credentials: Properly apply grpc.WithAuthority as the highest-priority option for setting authority, above the setting in the credentials themselves. (#8488)
    • Now that this WithAuthority is available, the credentials should not be used to override the authority.
  • round_robin: Randomize the order in which addresses are connected to in order to spread out initial RPC load between clients. (#8438)
  • server: Return status code INTERNAL when a client sends more than one request in unary and server streaming RPC. (#8385)
    • This is a behavior change but also a bug fix to bring gRPC-Go in line with the gRPC spec.

New Features

  • dns: Add an environment variable (GRPC_ENABLE_TXT_SERVICE_CONFIG) to provide a way to disable TXT lookups in the DNS resolver (by setting it to false). By default, TXT lookups are enabled, as they were previously. (#8377)

Bug Fixes

  • xds: Fix regression preventing empty node IDs in xDS bootstrap configuration. (#8476)
  • xds: Fix possible panic when certain invalid resources are encountered. (#8412)
  • xdsclient: Fix a rare panic caused by processing a response from a closed server. (#8389)
  • stats: Fix metric unit formatting by enclosing non-standard units like call and endpoint in curly braces to comply with UCUM and gRPC OpenTelemetry guidelines. (#8481)
  • xds: Fix possible panic when clusters are removed from the xds configuration. (#8428)
  • xdsclient: Fix a race causing "resource doesn not exist" when rapidly subscribing and unsubscribing to the same resource. (#8369)
  • client: When determining the authority, properly percent-encode (if needed, which is unlikely) when the target string omits the hostname and only specifies a port (grpc.NewClient(":<port-number-or-name>")). (#8488)

Release 1.74.3

Bug Fixes

  • xds: Fix a regression preventing empty node IDs in the bootstrap configuration. (#8476 , #8483)
  • xdsclient: Fix a data race caused while reporting load to LRS. (#8483)
  • server: Fix a regression preventing streams from being cancelled or timed out when blocked on flow control. (#8528)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.74.2&new-version=1.75.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mathew Merrick --- go.mod | 14 +++++++------- go.sum | 30 ++++++++++++++++-------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index ef42dd40e0..c680f11e9c 100644 --- a/go.mod +++ b/go.mod @@ -216,8 +216,8 @@ require ( golang.org/x/tools v0.36.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/apiserver v0.32.3 // indirect k8s.io/component-base v0.32.3 // indirect @@ -306,7 +306,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - google.golang.org/grpc v1.74.2 + google.golang.org/grpc v1.75.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 @@ -325,7 +325,7 @@ require ( github.com/containerd/containerd/api v1.8.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/go-jose/go-jose/v4 v4.0.5 // indirect + github.com/go-jose/go-jose/v4 v4.1.1 // indirect github.com/google/cel-go v0.24.1 // indirect github.com/moby/sys/userns v0.1.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect @@ -364,7 +364,7 @@ require ( github.com/Crocmagnon/fatcontext v0.7.1 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect @@ -636,8 +636,8 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.36.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.37.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect diff --git a/go.sum b/go.sum index f849c78814..3d324a19c7 100644 --- a/go.sum +++ b/go.sum @@ -163,8 +163,8 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rW github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= @@ -595,8 +595,8 @@ github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= -github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= +github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= +github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -1564,12 +1564,12 @@ go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDT go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= -go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= -go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= -go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -1855,6 +1855,8 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.223.0 h1:JUTaWEriXmEy5AhvdMgksGGPEFsYfUKaPEYXd4c3Wvc= google.golang.org/api v0.223.0/go.mod h1:C+RS7Z+dDwds2b+zoAk5hN/eSfsiCn0UDrYof/M4d2M= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1865,10 +1867,10 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= 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= @@ -1877,8 +1879,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= -google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 3769e6f312ab5f604868a3573a09a305be9255ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 18:34:10 -0400 Subject: [PATCH 143/448] deps: bump sigstore/cosign-installer from 3.9.2 to 3.10.0 (#1880) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.9.2 to 3.10.0.
Release notes

Sourced from sigstore/cosign-installer's releases.

v3.10.0

What's Changed

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v3.9.2...v3.10.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=3.9.2&new-version=3.10.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index f94d99f6d8..6f44f214cd 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -27,7 +27,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 4b81b789b0..9fe92ac3b2 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -32,7 +32,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -78,7 +78,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -124,7 +124,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -169,7 +169,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -212,7 +212,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -260,7 +260,7 @@ jobs: uses: docker/setup-qemu-action@v3 - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.2 + uses: sigstore/cosign-installer@v3.10.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From 7315eb73268e64dc83fb3d688fdd6e55ac0a7d25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:19:24 +0000 Subject: [PATCH 144/448] chore(deps): bump the npm_and_yarn group across 1 directory with 2 updates (#1900) Bumps the npm_and_yarn group with 2 updates in the /site directory: [tar-fs](https://github.com/mafintosh/tar-fs) and [webpack-dev-server](https://github.com/webpack/webpack-dev-server). Updates `tar-fs` from 2.1.3 to 2.1.4
Commits

Updates `tar-fs` from 3.0.9 to 3.1.1
Commits

Updates `webpack-dev-server` from 4.15.2 to 5.2.2
Release notes

Sourced from webpack-dev-server's releases.

v5.2.2

5.2.2 (2025-06-03)

Bug Fixes

  • "Overlay enabled" false positive (18e72ee)
  • do not crush when error is null for runtime errors (#5447) (309991f)
  • remove unnecessary header X_TEST (#5451) (64a6124)
  • respect the allowedHosts option for cross-origin header check (#5510) (03d1214)

v5.2.1

5.2.1 (2025-03-26)

Security

  • cross-origin requests are not allowed unless allowed by Access-Control-Allow-Origin header
  • requests with an IP addresses in the Origin header are not allowed to connect to WebSocket server unless configured by allowedHosts or it different from the Host header

The above changes may make the dev server not work if you relied on such behavior, but unfortunately they carry security risks, so they were considered as fixes.

Bug Fixes

  • prevent overlay for errors caught by React error boundaries (#5431) (8c1abc9)
  • take the first network found instead of the last one, this restores the same behavior as 5.0.4 (#5411) (ffd0b86)

v5.2.0

5.2.0 (2024-12-11)

Features

  • added getClientEntry and getClientHotEntry methods to get clients entries (dc642a8)

Bug Fixes

  • speed up initial client bundling (145b5d0)

v5.1.0

5.1.0 (2024-09-03)

Features

  • add visual progress indicators (a8f40b7)
  • added the app option to be Function (by default only with connect compatibility frameworks) (3096148)
  • allow the server option to be Function (#5275) (02a1c6d)
  • http2 support for connect and connect compatibility frameworks which support HTTP2 (#5267) (6509a3f)

... (truncated)

Changelog

Sourced from webpack-dev-server's changelog.

5.2.2 (2025-06-03)

Bug Fixes

  • "Overlay enabled" false positive (18e72ee)
  • do not crush when error is null for runtime errors (#5447) (309991f)
  • remove unnecessary header X_TEST (#5451) (64a6124)
  • respect the allowedHosts option for cross-origin header check (#5510) (03d1214)

5.2.1 (2025-03-26)

Security

  • cross-origin requests are not allowed unless allowed by Access-Control-Allow-Origin header
  • requests with an IP addresses in the Origin header are not allowed to connect to WebSocket server unless configured by allowedHosts or it different from the Host header

The above changes may make the dev server not work if you relied on such behavior, but unfortunately they carry security risks, so they were considered as fixes.

Bug Fixes

  • prevent overlay for errors caught by React error boundaries (#5431) (8c1abc9)
  • take the first network found instead of the last one, this restores the same behavior as 5.0.4 (#5411) (ffd0b86)

5.2.0 (2024-12-11)

Features

  • added getClientEntry and getClientHotEntry methods to get clients entries (dc642a8)

Bug Fixes

  • speed up initial client bundling (145b5d0)

5.1.0 (2024-09-03)

Features

  • add visual progress indicators (a8f40b7)
  • added the app option to be Function (by default only with connect compatibility frameworks) (3096148)
  • allow the server option to be Function (#5275) (02a1c6d)
  • http2 support for connect and connect compatibility frameworks which support HTTP2 (#5267) (6509a3f)

Bug Fixes

  • check the platform property to determinate the target (#5269) (c3b532c)

... (truncated)

Commits
  • 195a7e6 chore(release): 5.2.2
  • 620bef1 chore(deps): update (#5511)
  • 03d1214 fix: respect the allowedHosts option for cross-origin header check (#5510)
  • 5ba862e chore(deps-dev): bump the dependencies group across 1 directory with 7 update...
  • f7fec94 chore: fix typo (#5508)
  • 6ee8cd0 ci: add Node.js v24 (#5492)
  • d30f963 chore: update http-proxy-middleware to ^2.0.9 (#5503)
  • 66cf033 chore(deps-dev): bump the dependencies group with 2 updates (#5504)
  • 4367a5c refactor: use 'String#startsWith' & replace if-then-else (#5501)
  • 8e6604f chore(deps): bump the dependencies group across 1 directory with 4 updates (#...
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 2731 ++++++++++++++++++++++++---------------- site/package.json | 6 +- 2 files changed, 1670 insertions(+), 1067 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 3a5d4cd151..b67ddd76bc 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -8,9 +8,9 @@ "name": "retina", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.8.0", - "@docusaurus/plugin-ideal-image": "^3.8.0", - "@docusaurus/preset-classic": "^3.8.0", + "@docusaurus/core": "^3.9.1", + "@docusaurus/plugin-ideal-image": "^3.9.1", + "@docusaurus/preset-classic": "^3.9.1", "@mdx-js/react": "^3.0.0", "@types/react": "^18.3.7", "clsx": "^2.0.0", @@ -33,45 +33,117 @@ "node": ">=16.14" } }, - "node_modules/@algolia/autocomplete-core": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.9.tgz", - "integrity": "sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ==", - "license": "MIT", + "node_modules/@ai-sdk/gateway": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-1.0.39.tgz", + "integrity": "sha512-ijYCKG2sbn2RBVfIgaXNXvzHAf2HpFXxQODtjMI+T7Z4CLryflytchsZZ9qrGtsjiQVopKOV6m6kj4lq5fnbsg==", + "license": "Apache-2.0", "dependencies": { - "@algolia/autocomplete-plugin-algolia-insights": "1.17.9", - "@algolia/autocomplete-shared": "1.17.9" + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.12", + "@vercel/oidc": "3.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" } }, - "node_modules/@algolia/autocomplete-plugin-algolia-insights": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.9.tgz", - "integrity": "sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ==", - "license": "MIT", + "node_modules/@ai-sdk/provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", + "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.12.tgz", + "integrity": "sha512-ZtbdvYxdMoria+2SlNarEk6Hlgyf+zzcznlD55EAl+7VZvJaSg2sqPvwArY7L6TfDEDJsnCq0fdhBSkYo0Xqdg==", + "license": "Apache-2.0", "dependencies": { - "@algolia/autocomplete-shared": "1.17.9" + "@ai-sdk/provider": "2.0.0", + "@standard-schema/spec": "^1.0.0", + "eventsource-parser": "^3.0.5" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { - "search-insights": ">= 1 < 3" + "zod": "^3.25.76 || ^4.1.8" } }, - "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.9.tgz", - "integrity": "sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ==", + "node_modules/@ai-sdk/react": { + "version": "2.0.68", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.68.tgz", + "integrity": "sha512-dj21puWzGsNNrDE/26cytapMlS2/LD5NiN8TrU59fU/FVwuFHjwiepSfscBik54t/xNYRQIU+Qvt7lM7jnXJdg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider-utils": "3.0.12", + "ai": "5.0.68", + "swr": "^2.2.5", + "throttleit": "2.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "zod": "^3.25.76 || ^4.1.8" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@algolia/abtesting": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.6.0.tgz", + "integrity": "sha512-c4M/Z/KWkEG+RHpZsWKDTTlApXu3fe4vlABNcpankWBhdMe4oPZ/r4JxEr2zKUP6K+BT66tnp8UbHmgOd/vvqQ==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.17.9" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", + "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", + "@algolia/autocomplete-shared": "1.19.2" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", + "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.19.2" }, "peerDependencies": { - "@algolia/client-search": ">= 4.9.1 < 6", - "algoliasearch": ">= 4.9.1 < 6" + "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.9.tgz", - "integrity": "sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", + "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", "license": "MIT", "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -79,99 +151,99 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.25.0.tgz", - "integrity": "sha512-1pfQulNUYNf1Tk/svbfjfkLBS36zsuph6m+B6gDkPEivFmso/XnRgwDvjAx80WNtiHnmeNjIXdF7Gos8+OLHqQ==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.40.0.tgz", + "integrity": "sha512-qegVlgHtmiS8m9nEsuKUVhlw1FHsIshtt5nhNnA6EYz3g+tm9+xkVZZMzkrMLPP7kpoheHJZAwz2MYnHtwFa9A==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.25.0.tgz", - "integrity": "sha512-AFbG6VDJX/o2vDd9hqncj1B6B4Tulk61mY0pzTtzKClyTDlNP0xaUiEKhl6E7KO9I/x0FJF5tDCm0Hn6v5x18A==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.40.0.tgz", + "integrity": "sha512-Dw2c+6KGkw7mucnnxPyyMsIGEY8+hqv6oB+viYB612OMM3l8aNaWToBZMnNvXsyP+fArwq7XGR+k3boPZyV53A==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.25.0.tgz", - "integrity": "sha512-il1zS/+Rc6la6RaCdSZ2YbJnkQC6W1wiBO8+SH+DE6CPMWBU6iDVzH0sCKSAtMWl9WBxoN6MhNjGBnCv9Yy2bA==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.40.0.tgz", + "integrity": "sha512-dbE4+MJIDsTghG3hUYWBq7THhaAmqNqvW9g2vzwPf5edU4IRmuYpKtY3MMotes8/wdTasWG07XoaVhplJBlvdg==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.25.0.tgz", - "integrity": "sha512-blbjrUH1siZNfyCGeq0iLQu00w3a4fBXm0WRIM0V8alcAPo7rWjLbMJMrfBtzL9X5ic6wgxVpDADXduGtdrnkw==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.40.0.tgz", + "integrity": "sha512-SH6zlROyGUCDDWg71DlCnbbZ/zEHYPZC8k901EAaBVhvY43Ju8Wa6LAcMPC4tahcDBgkG2poBy8nJZXvwEWAlQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.25.0.tgz", - "integrity": "sha512-aywoEuu1NxChBcHZ1pWaat0Plw7A8jDMwjgRJ00Mcl7wGlwuPt5dJ/LTNcg3McsEUbs2MBNmw0ignXBw9Tbgow==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.40.0.tgz", + "integrity": "sha512-EgHjJEEf7CbUL9gJHI1ULmAtAFeym2cFNSAi1uwHelWgLPcnLjYW2opruPxigOV7NcetkGu+t2pcWOWmZFuvKQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.25.0.tgz", - "integrity": "sha512-a/W2z6XWKjKjIW1QQQV8PTTj1TXtaKx79uR3NGBdBdGvVdt24KzGAaN7sCr5oP8DW4D3cJt44wp2OY/fZcPAVA==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.40.0.tgz", + "integrity": "sha512-HvE1jtCag95DR41tDh7cGwrMk4X0aQXPOBIhZRmsBPolMeqRJz0kvfVw8VCKvA1uuoAkjFfTG0X0IZED+rKXoA==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.25.0.tgz", - "integrity": "sha512-9rUYcMIBOrCtYiLX49djyzxqdK9Dya/6Z/8sebPn94BekT+KLOpaZCuc6s0Fpfq7nx5J6YY5LIVFQrtioK9u0g==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.0.tgz", + "integrity": "sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" @@ -184,99 +256,86 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.25.0.tgz", - "integrity": "sha512-jJeH/Hk+k17Vkokf02lkfYE4A+EJX+UgnMhTLR/Mb+d1ya5WhE+po8p5a/Nxb6lo9OLCRl6w3Hmk1TX1e9gVbQ==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.40.0.tgz", + "integrity": "sha512-OfHnhE+P0f+p3i90Kmshf9Epgesw5oPV1IEUOY4Mq1HV7cQk16gvklVN1EaY/T9sVavl+Vc3g4ojlfpIwZFA4g==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.25.0.tgz", - "integrity": "sha512-Ls3i1AehJ0C6xaHe7kK9vPmzImOn5zBg7Kzj8tRYIcmCWVyuuFwCIsbuIIz/qzUf1FPSWmw0TZrGeTumk2fqXg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.40.0.tgz", + "integrity": "sha512-SWANV32PTKhBYvwKozeWP9HOnVabOixAuPdFFGoqtysTkkwutrtGI/rrh80tvG+BnQAmZX0vUmD/RqFZVfr/Yg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.25.0.tgz", - "integrity": "sha512-79sMdHpiRLXVxSjgw7Pt4R1aNUHxFLHiaTDnN2MQjHwJ1+o3wSseb55T9VXU4kqy3m7TUme3pyRhLk5ip/S4Mw==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.40.0.tgz", + "integrity": "sha512-1Qxy9I5bSb3mrhPk809DllMa561zl5hLsMR6YhIqNkqQ0OyXXQokvJ2zApSxvd39veRZZnhN+oGe+XNoNwLgkw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "@algolia/client-common": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.25.0.tgz", - "integrity": "sha512-JLaF23p1SOPBmfEqozUAgKHQrGl3z/Z5RHbggBu6s07QqXXcazEsub5VLonCxGVqTv6a61AAPr8J1G5HgGGjEw==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.40.0.tgz", + "integrity": "sha512-MGt94rdHfkrVjfN/KwUfWcnaeohYbWGINrPs96f5J7ZyRYpVLF+VtPQ2FmcddFvK4gnKXSu8BAi81hiIhUpm3w==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0" + "@algolia/client-common": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.25.0.tgz", - "integrity": "sha512-rtzXwqzFi1edkOF6sXxq+HhmRKDy7tz84u0o5t1fXwz0cwx+cjpmxu/6OQKTdOJFS92JUYHsG51Iunie7xbqfQ==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.40.0.tgz", + "integrity": "sha512-wXQ05JZZ10Dr642QVAkAZ4ZZlU+lh5r6dIBGmm9WElz+1EaQ6BNYtEOTV6pkXuFYsZpeJA89JpDOiwBOP9j24w==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0" + "@algolia/client-common": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.25.0.tgz", - "integrity": "sha512-ZO0UKvDyEFvyeJQX0gmZDQEvhLZ2X10K+ps6hViMo1HgE2V8em00SwNsQ+7E/52a+YiBkVWX61pJJJE44juDMQ==", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.40.0.tgz", + "integrity": "sha512-5qCRoySnzpbQVg2IPLGFCm4LF75pToxI5tdjOYgUMNL/um91aJ4dH3SVdBEuFlVsalxl8mh3bWPgkUmv6NpJiQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.25.0" + "@algolia/client-common": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -292,30 +351,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz", - "integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", - "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", + "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.4", - "@babel/parser": "^7.27.4", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.4", - "@babel/types": "^7.27.3", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -340,15 +399,15 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.3", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -393,17 +452,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "engines": { @@ -449,21 +508,30 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", - "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "resolve": "^1.22.10" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", @@ -491,14 +559,14 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -603,39 +671,39 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", - "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz", - "integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3" + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", - "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -708,13 +776,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", - "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -839,14 +907,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -888,9 +956,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz", - "integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.4.tgz", + "integrity": "sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -919,12 +987,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", - "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.28.3", "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { @@ -935,17 +1003,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", - "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.27.1", - "globals": "^11.1.0" + "@babel/traverse": "^7.28.4" }, "engines": { "node": ">=6.9.0" @@ -971,12 +1039,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.3.tgz", - "integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", + "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -1047,6 +1116,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", @@ -1298,15 +1383,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.3.tgz", - "integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.3", - "@babel/plugin-transform-parameters": "^7.27.1" + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" }, "engines": { "node": ">=6.9.0" @@ -1363,9 +1449,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", - "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1441,9 +1527,9 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz", - "integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1506,9 +1592,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.4.tgz", - "integrity": "sha512-Glp/0n8xuj+E1588otw5rjJkTXfzW7FjH3IIUrfqiZOPQCd2vbg8e+DQE8jK9g4V5/zrxFW+D9WM9gboRPELpQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1552,16 +1638,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.4.tgz", - "integrity": "sha512-D68nR5zxU64EUzV8i7T3R5XP0Xhrou/amNnddsRQssx6GrTLdZl1rLxyjtVZBd+v/NVX4AbTPOB5aU8thAZV1A==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", + "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "engines": { @@ -1657,12 +1743,12 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.1.tgz", - "integrity": "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", @@ -1739,12 +1825,12 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", + "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", @@ -1752,25 +1838,26 @@ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-import-assertions": "^7.27.1", "@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", "@babel/plugin-transform-async-to-generator": "^7.27.1", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.0", "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.3", "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", "@babel/plugin-transform-dotall-regex": "^7.27.1", "@babel/plugin-transform-duplicate-keys": "^7.27.1", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", "@babel/plugin-transform-exponentiation-operator": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", @@ -1787,15 +1874,15 @@ "@babel/plugin-transform-new-target": "^7.27.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.27.2", + "@babel/plugin-transform-object-rest-spread": "^7.28.0", "@babel/plugin-transform-object-super": "^7.27.1", "@babel/plugin-transform-optional-catch-binding": "^7.27.1", "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.7", "@babel/plugin-transform-private-methods": "^7.27.1", "@babel/plugin-transform-private-property-in-object": "^7.27.1", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.3", "@babel/plugin-transform-regexp-modifiers": "^7.27.1", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", @@ -1808,10 +1895,10 @@ "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", "semver": "^6.3.1" }, "engines": { @@ -1896,12 +1983,12 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.4.tgz", - "integrity": "sha512-H7QhL0ucCGOObsUETNbB2PuzF4gAvN8p32P6r91bX7M/hk4bx+3yz2hTwHL9d/Efzwu1upeb4/cd7oSxCzup3w==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz", + "integrity": "sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==", "license": "MIT", "dependencies": { - "core-js-pure": "^3.30.2" + "core-js-pure": "^3.43.0" }, "engines": { "node": ">=6.9.0" @@ -1922,27 +2009,27 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", - "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.4", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/types": "^7.28.4", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -1985,9 +2072,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", "funding": [ { "type": "github", @@ -2027,9 +2114,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", - "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", "funding": [ { "type": "github", @@ -2042,7 +2129,7 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "engines": { @@ -2117,10 +2204,39 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/@csstools/postcss-alpha-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-alpha-function/-/postcss-alpha-function-1.0.1.tgz", + "integrity": "sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-cascade-layers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.1.tgz", - "integrity": "sha512-XOfhI7GShVcKiKwmPAnWSqd2tBR0uxt+runAxttbSp/LY2U16yAVPmAf7e9q4JJ0d+xMNmpwNDLBXnmRCl3HMQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.2.tgz", + "integrity": "sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==", "funding": [ { "type": "github", @@ -2179,9 +2295,9 @@ } }, "node_modules/@csstools/postcss-color-function": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.10.tgz", - "integrity": "sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.12.tgz", + "integrity": "sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==", "funding": [ { "type": "github", @@ -2194,10 +2310,39 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-function-display-p3-linear": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function-display-p3-linear/-/postcss-color-function-display-p3-linear-1.0.1.tgz", + "integrity": "sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2208,9 +2353,9 @@ } }, "node_modules/@csstools/postcss-color-mix-function": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.10.tgz", - "integrity": "sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.12.tgz", + "integrity": "sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==", "funding": [ { "type": "github", @@ -2223,10 +2368,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2237,9 +2382,9 @@ } }, "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.0.tgz", - "integrity": "sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.2.tgz", + "integrity": "sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==", "funding": [ { "type": "github", @@ -2252,10 +2397,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2266,9 +2411,9 @@ } }, "node_modules/@csstools/postcss-content-alt-text": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.6.tgz", - "integrity": "sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.8.tgz", + "integrity": "sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==", "funding": [ { "type": "github", @@ -2283,7 +2428,36 @@ "dependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-contrast-color-function": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-contrast-color-function/-/postcss-contrast-color-function-2.0.12.tgz", + "integrity": "sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2347,9 +2521,9 @@ } }, "node_modules/@csstools/postcss-gamut-mapping": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.10.tgz", - "integrity": "sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.11.tgz", + "integrity": "sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==", "funding": [ { "type": "github", @@ -2362,7 +2536,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" }, @@ -2374,9 +2548,9 @@ } }, "node_modules/@csstools/postcss-gradients-interpolation-method": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.10.tgz", - "integrity": "sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.12.tgz", + "integrity": "sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==", "funding": [ { "type": "github", @@ -2389,10 +2563,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2403,9 +2577,9 @@ } }, "node_modules/@csstools/postcss-hwb-function": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.10.tgz", - "integrity": "sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.12.tgz", + "integrity": "sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==", "funding": [ { "type": "github", @@ -2418,10 +2592,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2432,9 +2606,9 @@ } }, "node_modules/@csstools/postcss-ic-unit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.2.tgz", - "integrity": "sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.4.tgz", + "integrity": "sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==", "funding": [ { "type": "github", @@ -2447,7 +2621,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -2481,9 +2655,9 @@ } }, "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz", - "integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.3.tgz", + "integrity": "sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==", "funding": [ { "type": "github", @@ -2542,9 +2716,9 @@ } }, "node_modules/@csstools/postcss-light-dark-function": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.9.tgz", - "integrity": "sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.11.tgz", + "integrity": "sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==", "funding": [ { "type": "github", @@ -2559,7 +2733,7 @@ "dependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2793,9 +2967,9 @@ } }, "node_modules/@csstools/postcss-oklab-function": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.10.tgz", - "integrity": "sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.12.tgz", + "integrity": "sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==", "funding": [ { "type": "github", @@ -2808,10 +2982,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2822,9 +2996,9 @@ } }, "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.1.0.tgz", - "integrity": "sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.2.1.tgz", + "integrity": "sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==", "funding": [ { "type": "github", @@ -2874,9 +3048,9 @@ } }, "node_modules/@csstools/postcss-relative-color-syntax": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.10.tgz", - "integrity": "sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.12.tgz", + "integrity": "sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==", "funding": [ { "type": "github", @@ -2889,10 +3063,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -2995,9 +3169,9 @@ } }, "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz", - "integrity": "sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.3.tgz", + "integrity": "sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==", "funding": [ { "type": "github", @@ -3010,7 +3184,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "postcss-value-parser": "^4.2.0" }, "engines": { @@ -3101,21 +3275,24 @@ } }, "node_modules/@docsearch/css": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.9.0.tgz", - "integrity": "sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.2.0.tgz", + "integrity": "sha512-65KU9Fw5fGsPPPlgIghonMcndyx1bszzrDQYLfierN+Ha29yotMHzVS94bPkZS6On9LS8dE4qmW4P/fGjtCf/g==", "license": "MIT" }, "node_modules/@docsearch/react": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.9.0.tgz", - "integrity": "sha512-mb5FOZYZIkRQ6s/NWnM98k879vu5pscWqTLubLFBO87igYYT4VzVazh4h5o/zCvTIZgEt3PvsCOMOswOUo9yHQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.2.0.tgz", + "integrity": "sha512-zSN/KblmtBcerf7Z87yuKIHZQmxuXvYc6/m0+qnjyNu+Ir67AVOagTa1zBqcxkVUVkmBqUExdcyrdo9hbGbqTw==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-core": "1.17.9", - "@algolia/autocomplete-preset-algolia": "1.17.9", - "@docsearch/css": "3.9.0", - "algoliasearch": "^5.14.2" + "@ai-sdk/react": "^2.0.30", + "@algolia/autocomplete-core": "1.19.2", + "@docsearch/css": "4.2.0", + "ai": "^5.0.30", + "algoliasearch": "^5.28.0", + "marked": "^16.3.0", + "zod": "^4.1.8" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", @@ -3139,9 +3316,9 @@ } }, "node_modules/@docusaurus/babel": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.0.tgz", - "integrity": "sha512-9EJwSgS6TgB8IzGk1L8XddJLhZod8fXT4ULYMx6SKqyCBqCFpVCEjR/hNXXhnmtVM2irDuzYoVLGWv7srG/VOA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.1.tgz", + "integrity": "sha512-/uoi3oG+wvbVWNBRfPrzrEslOSeLxrQEyWMywK51TLDFTANqIRivzkMusudh5bdDty8fXzCYUT+tg5t697jYqg==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3154,41 +3331,41 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/logger": "3.9.1", + "@docusaurus/utils": "3.9.1", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/bundler": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.0.tgz", - "integrity": "sha512-Rq4Z/MSeAHjVzBLirLeMcjLIAQy92pF1OI+2rmt18fSlMARfTGLWRE8Vb+ljQPTOSfJxwDYSzsK6i7XloD2rNA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.1.tgz", + "integrity": "sha512-E1c9DgNmAz4NqbNtiJVp4UgjLtr8O01IgtXD/NDQ4PZaK8895cMiTOgb3k7mN0qX8A3lb8vqyrPJ842+yMpuUg==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.8.0", - "@docusaurus/cssnano-preset": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/babel": "3.9.1", + "@docusaurus/cssnano-preset": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", "babel-loader": "^9.2.1", - "clean-css": "^5.3.2", + "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.8.1", + "css-loader": "^6.11.0", "css-minimizer-webpack-plugin": "^5.0.1", "cssnano": "^6.1.2", "file-loader": "^6.2.0", "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.1", + "mini-css-extract-plugin": "^2.9.2", "null-loader": "^4.0.1", - "postcss": "^8.4.26", - "postcss-loader": "^7.3.3", - "postcss-preset-env": "^10.1.0", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", "terser-webpack-plugin": "^5.3.9", "tslib": "^2.6.0", "url-loader": "^4.1.1", @@ -3196,7 +3373,7 @@ "webpackbar": "^6.0.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "@docusaurus/faster": "*" @@ -3243,18 +3420,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.0.tgz", - "integrity": "sha512-c7u6zFELmSGPEP9WSubhVDjgnpiHgDqMh1qVdCB7rTflh4Jx0msTYmMiO91Ez0KtHj4sIsDsASnjwfJ2IZp3Vw==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.8.0", - "@docusaurus/bundler": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.1.tgz", + "integrity": "sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.9.1", + "@docusaurus/bundler": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/mdx-loader": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3288,14 +3465,14 @@ "update-notifier": "^6.0.2", "webpack": "^5.95.0", "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^4.15.2", + "webpack-dev-server": "^5.2.2", "webpack-merge": "^6.0.1" }, "bin": { "docusaurus": "bin/docusaurus.mjs" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "@mdx-js/react": "^3.0.0", @@ -3318,47 +3495,47 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.0.tgz", - "integrity": "sha512-UJ4hAS2T0R4WNy+phwVff2Q0L5+RXW9cwlH6AEphHR5qw3m/yacfWcSK7ort2pMMbDn8uGrD38BTm4oLkuuNoQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.1.tgz", + "integrity": "sha512-2y7+s7RWQMqBg+9ejeKwvZs7Bdw/hHIVJIodwMXbs2kr+S48AhcmAfdOh6Cwm0unJb0hJUshN0ROwRoQMwl3xg==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.4.38", + "postcss": "^8.5.4", "postcss-sort-media-queries": "^5.2.0", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/logger": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.0.tgz", - "integrity": "sha512-7eEMaFIam5Q+v8XwGqF/n0ZoCld4hV4eCCgQkfcN9Mq5inoZa6PHHW9Wu6lmgzoK5Kx3keEeABcO2SxwraoPDQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.1.tgz", + "integrity": "sha512-C9iFzXwHzwvGlisE4bZx+XQE0JIqlGAYAd5LzpR7fEDgjctu7yL8bE5U4nTNywXKHURDzMt4RJK8V6+stFHVkA==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/lqip-loader": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.8.0.tgz", - "integrity": "sha512-8QYQsc5lgw7JdMABDEN6F9FE3JVDeRL+uDEfdwukYVggLI2sVfkfqWGHjH4r4szv02/z7Bv+hUn2pMuWqJm/cw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.9.1.tgz", + "integrity": "sha512-bCYHDxZ9U0M9pUdbUyrqyOmTuDZQw4MhZOdib+MZPmcor8U2spHnPW9+fagzJfmyoZ321X/tvEDSo3g+UxSM1Q==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", + "@docusaurus/logger": "3.9.1", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/lqip-loader/node_modules/sharp": { @@ -3385,14 +3562,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.0.tgz", - "integrity": "sha512-mDPSzssRnpjSdCGuv7z2EIAnPS1MHuZGTaRLwPn4oQwszu4afjWZ/60sfKjTnjBjI8Vl4OgJl2vMmfmiNDX4Ng==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.1.tgz", + "integrity": "sha512-/1PY8lqry8jCt0qZddJSpc0U2sH6XC27kVJZfpA7o2TiQ3mdBQyH5AVbj/B2m682B1ounE+XjI0LdpOkAQLPoA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/logger": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -3416,7 +3593,7 @@ "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3424,12 +3601,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.0.tgz", - "integrity": "sha512-/uMb4Ipt5J/QnD13MpnoC/A4EYAe6DKNWqTWLlGrqsPJwJv73vSwkA25xnYunwfqWk0FlUQfGv/Swdh5eCCg7g==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.1.tgz", + "integrity": "sha512-YBce3GbJGGcMbJTyHcnEOMvdXqg41pa5HsrMCGA5Rm4z0h0tHS6YtEldj0mlfQRhCG7Y0VD66t2tb87Aom+11g==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.9.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3443,19 +3620,19 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.8.0.tgz", - "integrity": "sha512-0SlOTd9R55WEr1GgIXu+hhTT0hzARYx3zIScA5IzpdekZQesI/hKEa5LPHBd415fLkWMjdD59TaW/3qQKpJ0Lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.1.tgz", + "integrity": "sha512-vT6kIimpJLWvW9iuWzH4u7VpTdsGlmn4yfyhq0/Kb1h4kf9uVouGsTmrD7WgtYBUG1P+TSmQzUUQa+ALBSRTig==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/mdx-loader": "3.9.1", + "@docusaurus/theme-common": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -3468,7 +3645,7 @@ "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "@docusaurus/plugin-content-docs": "*", @@ -3477,20 +3654,20 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.0.tgz", - "integrity": "sha512-fRDMFLbUN6eVRXcjP8s3Y7HpAt9pzPYh1F/7KKXOCxvJhjjCtbon4VJW0WndEPInVz4t8QUXn5QZkU2tGVCE2g==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", + "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/mdx-loader": "3.9.1", + "@docusaurus/module-type-aliases": "3.9.1", + "@docusaurus/theme-common": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -3502,7 +3679,7 @@ "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3510,22 +3687,22 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.8.0.tgz", - "integrity": "sha512-39EDx2y1GA0Pxfion5tQZLNJxL4gq6susd1xzetVBjVIQtwpCdyloOfQBAgX0FylqQxfJrYqL0DIUuq7rd7uBw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.1.tgz", + "integrity": "sha512-/1wFzRnXYASI+Nv9ck9IVPIMw0O5BGQ8ZVhDzEwhkL+tl44ycvSnY6PIe6rW2HLxsw61Z3WFwAiU8+xMMtMZpg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/mdx-loader": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3533,35 +3710,36 @@ } }, "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.8.0.tgz", - "integrity": "sha512-/VBTNymPIxQB8oA3ZQ4GFFRYdH4ZxDRRBECxyjRyv486mfUPXfcdk+im4S5mKWa6EK2JzBz95IH/Wu0qQgJ5yQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.1.tgz", + "integrity": "sha512-/QyW2gRCk/XE3ttCK/ERIgle8KJ024dBNKMu6U5SmpJvuT2il1n5jR/48Pp/9wEwut8WVml4imNm6X8JsL5A0Q==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.8.0.tgz", - "integrity": "sha512-teonJvJsDB9o2OnG6ifbhblg/PXzZvpUKHFgD8dOL1UJ58u0lk8o0ZOkvaYEBa9nDgqzoWrRk9w+e3qaG2mOhQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.1.tgz", + "integrity": "sha512-qPeAuk0LccC251d7jg2MRhNI+o7niyqa924oEM/AxnZJvIpMa596aAxkRImiAqNN6+gtLE1Hkrz/RHUH2HDGsA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", "fs-extra": "^11.1.1", "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3569,18 +3747,18 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.8.0.tgz", - "integrity": "sha512-aKKa7Q8+3xRSRESipNvlFgNp3FNPELKhuo48Cg/svQbGNwidSHbZT03JqbW4cBaQnyyVchO1ttk+kJ5VC9Gx0w==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.1.tgz", + "integrity": "sha512-k4Qq2HphqOrIU/CevGPdEO1yJnWUI8m0zOJsYt5NfMJwNsIn/gDD6gv/DKD+hxHndQT5pacsfBd4BWHZVNVroQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3588,19 +3766,19 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.8.0.tgz", - "integrity": "sha512-ugQYMGF4BjbAW/JIBtVcp+9eZEgT9HRdvdcDudl5rywNPBA0lct+lXMG3r17s02rrhInMpjMahN3Yc9Cb3H5/g==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.1.tgz", + "integrity": "sha512-n9BURBiQyJKI/Ecz35IUjXYwXcgNCSq7/eA07+ZYcDiSyH2p/EjPf8q/QcZG3CyEJPZ/SzGkDHePfcVPahY4Gg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3608,18 +3786,18 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.8.0.tgz", - "integrity": "sha512-9juRWxbwZD3SV02Jd9QB6yeN7eu+7T4zB0bvJLcVQwi+am51wAxn2CwbdL0YCCX+9OfiXbADE8D8Q65Hbopu/w==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.1.tgz", + "integrity": "sha512-rZAQZ25ZuXaThBajxzLjXieTDUCMmBzfAA6ThElQ3o7Q+LEpOjCIrwGFau0KLY9HeG6x91+FwwsAM8zeApYDrg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3627,23 +3805,23 @@ } }, "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.8.0.tgz", - "integrity": "sha512-DPjOP+IceHDaGdQNowW2zQmDJF5keQgQZr58p2rY82f5W/SwcNwpPuLKzzqfym4xJTo8EtqpdeqWnY63kzUQKQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.1.tgz", + "integrity": "sha512-9d4VKG/jSQj4sf9wKYpr+5q4wPOnEAqGAMcLLvuh+LXmCPmrKwMOrr9M0ycCaYdE0eL/uOrLhVa5E1H2MuTEvA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/lqip-loader": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/lqip-loader": "3.9.1", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/theme-translations": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "sharp": "^0.32.3", "tslib": "^2.6.0", "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "jimp": "*", @@ -3679,23 +3857,23 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.8.0.tgz", - "integrity": "sha512-fGpOIyJvNiuAb90nSJ2Gfy/hUOaDu6826e5w5UxPmbpCIc7KlBHNAZ5g4L4ZuHhc4hdfq4mzVBsQSnne+8Ze1g==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.1.tgz", + "integrity": "sha512-k/bf5cXDxAJUYTzqatgFJwmZsLUbIgl6S8AdZMKGG2Mv2wcOHt+EQNN9qPyWZ5/9cFj+Q8f8DN+KQheBMYLong==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3703,22 +3881,22 @@ } }, "node_modules/@docusaurus/plugin-svgr": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.8.0.tgz", - "integrity": "sha512-kEDyry+4OMz6BWLG/lEqrNsL/w818bywK70N1gytViw4m9iAmoxCUT7Ri9Dgs7xUdzCHJ3OujolEmD88Wy44OA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.1.tgz", + "integrity": "sha512-TeZOXT2PSdTNR1OpDJMkYqFyX7MMhbd4t16hQByXksgZQCXNyw3Dio+KaDJ2Nj+LA4WkOvsk45bWgYG5MAaXSQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3726,29 +3904,29 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.8.0.tgz", - "integrity": "sha512-qOu6tQDOWv+rpTlKu+eJATCJVGnABpRCPuqf7LbEaQ1mNY//N/P8cHQwkpAU+aweQfarcZ0XfwCqRHJfjeSV/g==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.1.tgz", + "integrity": "sha512-ZHga2xsxxsyd0dN1BpLj8S889Eu9eMBuj2suqxdw/vaaXu/FjJ8KEGbcaeo6nHPo8VQcBBnPEdkBtSDm2TfMNw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/plugin-content-blog": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/plugin-content-pages": "3.8.0", - "@docusaurus/plugin-css-cascade-layers": "3.8.0", - "@docusaurus/plugin-debug": "3.8.0", - "@docusaurus/plugin-google-analytics": "3.8.0", - "@docusaurus/plugin-google-gtag": "3.8.0", - "@docusaurus/plugin-google-tag-manager": "3.8.0", - "@docusaurus/plugin-sitemap": "3.8.0", - "@docusaurus/plugin-svgr": "3.8.0", - "@docusaurus/theme-classic": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-search-algolia": "3.8.0", - "@docusaurus/types": "3.8.0" + "@docusaurus/core": "3.9.1", + "@docusaurus/plugin-content-blog": "3.9.1", + "@docusaurus/plugin-content-docs": "3.9.1", + "@docusaurus/plugin-content-pages": "3.9.1", + "@docusaurus/plugin-css-cascade-layers": "3.9.1", + "@docusaurus/plugin-debug": "3.9.1", + "@docusaurus/plugin-google-analytics": "3.9.1", + "@docusaurus/plugin-google-gtag": "3.9.1", + "@docusaurus/plugin-google-tag-manager": "3.9.1", + "@docusaurus/plugin-sitemap": "3.9.1", + "@docusaurus/plugin-svgr": "3.9.1", + "@docusaurus/theme-classic": "3.9.1", + "@docusaurus/theme-common": "3.9.1", + "@docusaurus/theme-search-algolia": "3.9.1", + "@docusaurus/types": "3.9.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3779,31 +3957,30 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.8.0.tgz", - "integrity": "sha512-nQWFiD5ZjoT76OaELt2n33P3WVuuCz8Dt5KFRP2fCBo2r9JCLsp2GJjZpnaG24LZ5/arRjv4VqWKgpK0/YLt7g==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/plugin-content-blog": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/plugin-content-pages": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.1.tgz", + "integrity": "sha512-LrAIu/mQ04nG6s1cssC0TMmICD8twFIIn/hJ5Pd9uIPQvtKnyAKEn12RefopAul5KfMo9kixPaqogV5jIJr26w==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/mdx-loader": "3.9.1", + "@docusaurus/module-type-aliases": "3.9.1", + "@docusaurus/plugin-content-blog": "3.9.1", + "@docusaurus/plugin-content-docs": "3.9.1", + "@docusaurus/plugin-content-pages": "3.9.1", + "@docusaurus/theme-common": "3.9.1", + "@docusaurus/theme-translations": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", "infima": "0.2.0-alpha.45", "lodash": "^4.17.21", "nprogress": "^0.2.0", - "postcss": "^8.4.26", + "postcss": "^8.5.4", "prism-react-renderer": "^2.3.0", "prismjs": "^1.29.0", "react-router-dom": "^5.3.4", @@ -3812,7 +3989,7 @@ "utility-types": "^3.10.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3820,15 +3997,15 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.0.tgz", - "integrity": "sha512-YqV2vAWpXGLA+A3PMLrOMtqgTHJLDcT+1Caa6RF7N4/IWgrevy5diY8oIHFkXR/eybjcrFFjUPrHif8gSGs3Tw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.1.tgz", + "integrity": "sha512-j9adi961F+6Ps9d0jcb5BokMcbjXAAJqKkV43eo8nh4YgmDj7KUNDX4EnOh/MjTQeO06oPY5cxp3yUXdW/8Ggw==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/mdx-loader": "3.9.1", + "@docusaurus/module-type-aliases": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3839,7 +4016,7 @@ "utility-types": "^3.10.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "@docusaurus/plugin-content-docs": "*", @@ -3848,21 +4025,21 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.0.tgz", - "integrity": "sha512-GBZ5UOcPgiu6nUw153+0+PNWvFKweSnvKIL6Rp04H9olKb475jfKjAwCCtju5D2xs5qXHvCMvzWOg5o9f6DtuQ==", - "license": "MIT", - "dependencies": { - "@docsearch/react": "^3.9.0", - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", - "algoliasearch": "^5.17.1", - "algoliasearch-helper": "^3.22.6", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.1.tgz", + "integrity": "sha512-WjM28bzlgfT6nHlEJemkwyGVpvGsZWPireV/w+wZ1Uo64xCZ8lNOb4xwQRukDaLSed3oPBN0gSnu06l5VuCXHg==", + "license": "MIT", + "dependencies": { + "@docsearch/react": "^3.9.0 || ^4.1.0", + "@docusaurus/core": "3.9.1", + "@docusaurus/logger": "3.9.1", + "@docusaurus/plugin-content-docs": "3.9.1", + "@docusaurus/theme-common": "3.9.1", + "@docusaurus/theme-translations": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-validation": "3.9.1", + "algoliasearch": "^5.37.0", + "algoliasearch-helper": "^3.26.0", "clsx": "^2.0.0", "eta": "^2.2.0", "fs-extra": "^11.1.1", @@ -3871,7 +4048,7 @@ "utility-types": "^3.10.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -3879,16 +4056,16 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.0.tgz", - "integrity": "sha512-1DTy/snHicgkCkryWq54fZvsAglTdjTx4qjOXgqnXJ+DIty1B+aPQrAVUu8LiM+6BiILfmNxYsxhKTj+BS3PZg==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.1.tgz", + "integrity": "sha512-mUQd49BSGKTiM6vP9+JFgRJL28lMIN3PUvXjF3rzuOHMByUZUBNwCt26Z23GkKiSIOrRkjKoaBNTipR/MHdYSQ==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/tsconfig": { @@ -3899,13 +4076,14 @@ "license": "MIT" }, "node_modules/@docusaurus/types": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.0.tgz", - "integrity": "sha512-RDEClpwNxZq02c+JlaKLWoS13qwWhjcNsi2wG1UpzmEnuti/z1Wx4SGpqbUqRPNSd8QWWePR8Cb7DvG0VN/TtA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.1.tgz", + "integrity": "sha512-ElekJ29sk39s5LTEZMByY1c2oH9FMtw7KbWFU3BtuQ1TytfIK39HhUivDEJvm5KCLyEnnfUZlvSNDXeyk0vzAA==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", "@types/react": "*", "commander": "^5.1.0", "joi": "^17.9.2", @@ -3920,14 +4098,14 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.0.tgz", - "integrity": "sha512-2wvtG28ALCN/A1WCSLxPASFBFzXCnP0YKCAFIPcvEb6imNu1wg7ni/Svcp71b3Z2FaOFFIv4Hq+j4gD7gA0yfQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.1.tgz", + "integrity": "sha512-YAL4yhhWLl9DXuf5MVig260a6INz4MehrBGFU/CZu8yXmRiYEuQvRFWh9ZsjfAOyaG7za1MNmBVZ4VVAi/CiJA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/logger": "3.9.1", + "@docusaurus/types": "3.9.1", + "@docusaurus/utils-common": "3.9.1", "escape-string-regexp": "^4.0.0", "execa": "5.1.1", "file-loader": "^6.2.0", @@ -3948,31 +4126,31 @@ "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/utils-common": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.0.tgz", - "integrity": "sha512-3TGF+wVTGgQ3pAc9+5jVchES4uXUAhAt9pwv7uws4mVOxL4alvU3ue/EZ+R4XuGk94pDy7CNXjRXpPjlfZXQfw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.1.tgz", + "integrity": "sha512-4M1u5Q8Zn2CYL2TJ864M51FV4YlxyGyfC3x+7CLuR6xsyTVNBNU4QMcPgsTHRS9J2+X6Lq7MyH6hiWXyi/sXUQ==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.9.1", "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.0.tgz", - "integrity": "sha512-MrnEbkigr54HkdFeg8e4FKc4EF+E9dlVwsY3XQZsNkbv3MKZnbHQ5LsNJDIKDROFe8PBf5C4qCAg5TPBpsjrjg==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.1.tgz", + "integrity": "sha512-5bzab5si3E1udrlZuVGR17857Lfwe8iFPoy5AvMP9PXqDfoyIKT7gDQgAmxdRDMurgHaJlyhXEHHdzDKkOxxZQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/logger": "3.9.1", + "@docusaurus/utils": "3.9.1", + "@docusaurus/utils-common": "3.9.1", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -3980,7 +4158,7 @@ "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } }, "node_modules/@emnapi/runtime": { @@ -4379,17 +4557,23 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -4400,37 +4584,142 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/buffers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.0.tgz", + "integrity": "sha512-6RX+W5a+ZUY/c/7J5s5jK9UinLfJo5oWKh84fb4X0yK2q4WXEWUWZWuEMjvCb1YNUQhEAhUfr5scEGOH7jC4YQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.20.0.tgz", + "integrity": "sha512-adcXFVorSQULtT4XDL0giRLr2EVGIcyWm6eQKZWTrRA4EEydGOY8QVQtL0PaITQpUyu+lOd/QOicw6vdy1v8QQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "license": "MIT", + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, "node_modules/@leichtgewicht/ip-codec": { @@ -4526,6 +4815,15 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -4619,6 +4917,12 @@ "micromark-util-symbol": "^1.0.1" } }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -4897,9 +5201,9 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "license": "MIT", "dependencies": { "@types/connect": "*", @@ -4979,9 +5283,9 @@ } }, "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", "license": "MIT", "dependencies": { "@types/body-parser": "*", @@ -4991,21 +5295,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", - "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/express/node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "version": "4.19.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", + "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -5045,15 +5337,15 @@ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" }, "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "license": "MIT" }, "node_modules/@types/http-proxy": { - "version": "1.17.15", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", - "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "version": "1.17.16", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", + "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5123,9 +5415,9 @@ } }, "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5147,9 +5439,9 @@ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "license": "MIT" }, "node_modules/@types/range-parser": { @@ -5198,9 +5490,9 @@ } }, "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "license": "MIT" }, "node_modules/@types/sax": { @@ -5213,12 +5505,11 @@ } }, "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.0.tgz", + "integrity": "sha512-zBF6vZJn1IaMpg3xUF25VK3gd3l8zwE0ZLRX7dsQyQi+jp4E8mMDJNGDYnYse+bQhYwWERTxVwHpi3dMOq7RKQ==", "license": "MIT", "dependencies": { - "@types/mime": "^1", "@types/node": "*" } }, @@ -5232,14 +5523,24 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.9.tgz", + "integrity": "sha512-dOTIuqpWLyl3BBXU3maNQsS4A3zuuoYRNIvYSxxhebPfXg2mzWQEPne/nlJ37yOse6uGgR386uTpdsx4D0QZWA==", "license": "MIT", "dependencies": { "@types/http-errors": "*", "@types/node": "*", - "@types/send": "*" + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" } }, "node_modules/@types/sockjs": { @@ -5258,9 +5559,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5287,6 +5588,15 @@ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, + "node_modules/@vercel/oidc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.2.tgz", + "integrity": "sha512-JekxQ0RApo4gS4un/iMGsIL1/k4KUBe3HmnGcDvzHuFBdQdudEJgTqcsJC7y6Ul4Yw5CeykgvQbX2XeEJd0+DA==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -5530,6 +5840,24 @@ "node": ">=8" } }, + "node_modules/ai": { + "version": "5.0.68", + "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.68.tgz", + "integrity": "sha512-SB6r+4TkKVlSg2ozGBSfuf6Is5hrcX/bpGBzOoyHIN3b4ILGhaly0IHEvP8+3GGIHXqtkPVEUmR6V05jKdjNlg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "1.0.39", + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.12", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -5576,33 +5904,34 @@ } }, "node_modules/algoliasearch": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.25.0.tgz", - "integrity": "sha512-n73BVorL4HIwKlfJKb4SEzAYkR3Buwfwbh+MYxg2mloFph2fFGV58E90QTzdbfzWrLn4HE5Czx/WTjI8fcHaMg==", - "license": "MIT", - "dependencies": { - "@algolia/client-abtesting": "5.25.0", - "@algolia/client-analytics": "5.25.0", - "@algolia/client-common": "5.25.0", - "@algolia/client-insights": "5.25.0", - "@algolia/client-personalization": "5.25.0", - "@algolia/client-query-suggestions": "5.25.0", - "@algolia/client-search": "5.25.0", - "@algolia/ingestion": "1.25.0", - "@algolia/monitoring": "1.25.0", - "@algolia/recommend": "5.25.0", - "@algolia/requester-browser-xhr": "5.25.0", - "@algolia/requester-fetch": "5.25.0", - "@algolia/requester-node-http": "5.25.0" + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.0.tgz", + "integrity": "sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.6.0", + "@algolia/client-abtesting": "5.40.0", + "@algolia/client-analytics": "5.40.0", + "@algolia/client-common": "5.40.0", + "@algolia/client-insights": "5.40.0", + "@algolia/client-personalization": "5.40.0", + "@algolia/client-query-suggestions": "5.40.0", + "@algolia/client-search": "5.40.0", + "@algolia/ingestion": "1.40.0", + "@algolia/monitoring": "1.40.0", + "@algolia/recommend": "5.40.0", + "@algolia/requester-browser-xhr": "5.40.0", + "@algolia/requester-fetch": "5.40.0", + "@algolia/requester-node-http": "5.40.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.25.0.tgz", - "integrity": "sha512-vQoK43U6HXA9/euCqLjvyNdM4G2Fiu/VFp4ae0Gau9sZeIKBPvUPnXfLYAe65Bg7PFuw03coeu5K6lTPSXRObw==", + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz", + "integrity": "sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==", "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" @@ -5702,6 +6031,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -5828,13 +6158,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", - "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.4", + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { @@ -5851,25 +6181,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", - "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.4" + "@babel/helper-define-polyfill-provider": "^0.6.5" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5981,6 +6311,15 @@ } ] }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.16.tgz", + "integrity": "sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -6005,11 +6344,15 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { @@ -6071,9 +6414,9 @@ "license": "MIT" }, "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -6128,9 +6471,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", "funding": [ { "type": "opencollective", @@ -6147,9 +6490,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -6187,6 +6531,21 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -6332,9 +6691,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001720", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", - "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", + "version": "1.0.30001750", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001750.tgz", + "integrity": "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==", "funding": [ { "type": "opencollective", @@ -6464,15 +6823,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -6485,6 +6839,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -6731,9 +7088,9 @@ } }, "node_modules/compressible/node_modules/mime-db": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", - "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -6875,18 +7232,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, - "node_modules/copy-text-to-clipboard": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", - "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/copy-webpack-plugin": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", @@ -6965,12 +7310,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", + "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.26.3" }, "funding": { "type": "opencollective", @@ -6978,9 +7323,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.42.0.tgz", - "integrity": "sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.46.0.tgz", + "integrity": "sha512-NMCW30bHNofuhwLhYPt66OLOKTMbOhgTTatKVbaQC3KRHpTCiRIBYvtshr+NBYSnBxwAFhjW/RfJ0XbIjS16rw==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -7097,9 +7442,9 @@ } }, "node_modules/css-declaration-sorter": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", - "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.3.0.tgz", + "integrity": "sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ==", "license": "ISC", "engines": { "node": "^14 || ^16 || >=18" @@ -7109,9 +7454,9 @@ } }, "node_modules/css-has-pseudo": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz", - "integrity": "sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.3.tgz", + "integrity": "sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==", "funding": [ { "type": "github", @@ -7272,9 +7617,9 @@ } }, "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", @@ -7317,9 +7662,9 @@ } }, "node_modules/cssdb": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.3.0.tgz", - "integrity": "sha512-c7bmItIg38DgGjSwDPZOYF/2o0QU/sSgkWOMyl8votOfgFuyiFKWPesmCGEsrGLxEA9uL540cp8LdaGEjUGsZQ==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.4.2.tgz", + "integrity": "sha512-PzjkRkRUS+IHDJohtxkIczlxPPZqRo0nXplsYXOMBRPjcVRjj1W4DfvRgshUYTVuUigU7ptVYkFJQ7abUB0nyg==", "funding": [ { "type": "opencollective", @@ -7485,11 +7830,12 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -7555,16 +7901,32 @@ "node": ">=0.10.0" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "license": "BSD-2-Clause", + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "license": "MIT", "dependencies": { - "execa": "^5.0.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">= 10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/defer-to-connect": { @@ -7596,6 +7958,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", "engines": { "node": ">=8" } @@ -7979,9 +8342,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.161", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz", - "integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==", + "version": "1.5.234", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.234.tgz", + "integrity": "sha512-RXfEp2x+VRYn8jbKfQlRImzoJU01kyDvVPBmG39eU2iuRVhuS6vQNocB8J0/8GrIMLnPzgz4eW6WiRnJkTuNWg==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -8055,9 +8418,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -8376,6 +8739,15 @@ "node": ">=0.8.x" } }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -8557,9 +8929,19 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause" }, "node_modules/fastq": { @@ -8786,9 +9168,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -8870,21 +9252,12 @@ "node": ">=14.14" } }, - "node_modules/fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -8897,6 +9270,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9013,29 +9387,11 @@ "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", "license": "ISC" }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -9043,6 +9399,22 @@ "node": ">= 6" } }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -9070,15 +9442,6 @@ "node": ">=10" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -9684,22 +10047,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -9863,9 +10210,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", "license": "MIT" }, "node_modules/http-proxy": { @@ -9939,6 +10286,15 @@ "node": ">=10.17.0" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -10057,15 +10413,6 @@ "node": ">=12" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -10133,6 +10480,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -10202,6 +10550,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -10225,6 +10574,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10241,6 +10591,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -10254,8 +10605,41 @@ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "license": "MIT", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-installed-globally": { @@ -10273,6 +10657,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-network-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-npm": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", @@ -10351,6 +10747,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", "dependencies": { "is-docker": "^2.0.0" }, @@ -10492,6 +10889,12 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -10559,13 +10962,13 @@ } }, "node_modules/launch-editor": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", - "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz", + "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", "license": "MIT", "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" } }, "node_modules/leven": { @@ -10739,6 +11142,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.0.tgz", + "integrity": "sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -11166,14 +11581,21 @@ } }, "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.49.0.tgz", + "integrity": "sha512-L9uC9vGuc4xFybbdOpRLoOAOq1YEBBsocCs5NVW32DfU+CZWWIn3OVF+lB8Gp4ttBVSMazwrTrjv8ussX/e3VQ==", + "license": "Apache-2.0", "dependencies": { - "fs-monkey": "^1.0.4" + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" }, - "engines": { - "node": ">= 4.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, "node_modules/merge-descriptors": { @@ -13059,9 +13481,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", - "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", + "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", @@ -13127,9 +13549,10 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -13145,15 +13568,16 @@ } }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -13230,9 +13654,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", + "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", "license": "MIT" }, "node_modules/nopt": { @@ -13253,6 +13677,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -13378,9 +13803,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -13472,6 +13897,7 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -13572,16 +13998,20 @@ } }, "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "license": "MIT", "dependencies": { - "@types/retry": "0.12.0", + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", "retry": "^0.13.1" }, "engines": { - "node": ">=8" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-timeout": { @@ -13709,9 +14139,9 @@ } }, "node_modules/parse5/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -13747,14 +14177,6 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", @@ -13825,9 +14247,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -13844,9 +14266,9 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -13922,9 +14344,9 @@ } }, "node_modules/postcss-color-functional-notation": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.10.tgz", - "integrity": "sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.12.tgz", + "integrity": "sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==", "funding": [ { "type": "github", @@ -13937,10 +14359,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -14065,9 +14487,9 @@ } }, "node_modules/postcss-custom-properties": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.5.tgz", - "integrity": "sha512-UWf/vhMapZatv+zOuqlfLmYXeOhhHLh8U8HAKGI2VJ00xLRYoAJh4xv8iX6FB6+TLXeDnm0DBLMi00E0hodbQw==", + "version": "14.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz", + "integrity": "sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==", "funding": [ { "type": "github", @@ -14236,9 +14658,9 @@ } }, "node_modules/postcss-double-position-gradients": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.2.tgz", - "integrity": "sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.4.tgz", + "integrity": "sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==", "funding": [ { "type": "github", @@ -14251,7 +14673,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, @@ -14396,9 +14818,9 @@ } }, "node_modules/postcss-lab-function": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz", - "integrity": "sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.12.tgz", + "integrity": "sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==", "funding": [ { "type": "github", @@ -14411,10 +14833,10 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/utilities": "^2.0.0" }, "engines": { @@ -14641,9 +15063,9 @@ } }, "node_modules/postcss-nesting": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", - "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", + "integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==", "funding": [ { "type": "github", @@ -14656,7 +15078,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-resolve-nested": "^3.1.0", "@csstools/selector-specificity": "^5.0.0", "postcss-selector-parser": "^7.0.0" }, @@ -14668,9 +15090,9 @@ } }, "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz", - "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", + "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", "funding": [ { "type": "github", @@ -14955,9 +15377,9 @@ } }, "node_modules/postcss-preset-env": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.0.tgz", - "integrity": "sha512-cl13sPBbSqo1Q7Ryb19oT5NZO5IHFolRbIMdgDq4f9w1MHYiL6uZS7uSsjXJ1KzRIcX5BMjEeyxmAevVXENa3Q==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.4.0.tgz", + "integrity": "sha512-2kqpOthQ6JhxqQq1FSAAZGe9COQv75Aw8WbsOvQVNJ2nSevc9Yx/IKZGuZ7XJ+iOTtVon7LfO7ELRzg8AZ+sdw==", "funding": [ { "type": "github", @@ -14970,20 +15392,23 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/postcss-cascade-layers": "^5.0.1", - "@csstools/postcss-color-function": "^4.0.10", - "@csstools/postcss-color-mix-function": "^3.0.10", - "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.0", - "@csstools/postcss-content-alt-text": "^2.0.6", + "@csstools/postcss-alpha-function": "^1.0.1", + "@csstools/postcss-cascade-layers": "^5.0.2", + "@csstools/postcss-color-function": "^4.0.12", + "@csstools/postcss-color-function-display-p3-linear": "^1.0.1", + "@csstools/postcss-color-mix-function": "^3.0.12", + "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.2", + "@csstools/postcss-content-alt-text": "^2.0.8", + "@csstools/postcss-contrast-color-function": "^2.0.12", "@csstools/postcss-exponential-functions": "^2.0.9", "@csstools/postcss-font-format-keywords": "^4.0.0", - "@csstools/postcss-gamut-mapping": "^2.0.10", - "@csstools/postcss-gradients-interpolation-method": "^5.0.10", - "@csstools/postcss-hwb-function": "^4.0.10", - "@csstools/postcss-ic-unit": "^4.0.2", + "@csstools/postcss-gamut-mapping": "^2.0.11", + "@csstools/postcss-gradients-interpolation-method": "^5.0.12", + "@csstools/postcss-hwb-function": "^4.0.12", + "@csstools/postcss-ic-unit": "^4.0.4", "@csstools/postcss-initial": "^2.0.1", - "@csstools/postcss-is-pseudo-class": "^5.0.1", - "@csstools/postcss-light-dark-function": "^2.0.9", + "@csstools/postcss-is-pseudo-class": "^5.0.3", + "@csstools/postcss-light-dark-function": "^2.0.11", "@csstools/postcss-logical-float-and-clear": "^3.0.0", "@csstools/postcss-logical-overflow": "^2.0.0", "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", @@ -14993,40 +15418,40 @@ "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", "@csstools/postcss-nested-calc": "^4.0.0", "@csstools/postcss-normalize-display-values": "^4.0.0", - "@csstools/postcss-oklab-function": "^4.0.10", - "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-oklab-function": "^4.0.12", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", "@csstools/postcss-random-function": "^2.0.1", - "@csstools/postcss-relative-color-syntax": "^3.0.10", + "@csstools/postcss-relative-color-syntax": "^3.0.12", "@csstools/postcss-scope-pseudo-class": "^4.0.1", "@csstools/postcss-sign-functions": "^1.1.4", "@csstools/postcss-stepped-value-functions": "^4.0.9", - "@csstools/postcss-text-decoration-shorthand": "^4.0.2", + "@csstools/postcss-text-decoration-shorthand": "^4.0.3", "@csstools/postcss-trigonometric-functions": "^4.0.9", "@csstools/postcss-unset-value": "^4.0.0", "autoprefixer": "^10.4.21", - "browserslist": "^4.24.5", + "browserslist": "^4.26.0", "css-blank-pseudo": "^7.0.1", - "css-has-pseudo": "^7.0.2", + "css-has-pseudo": "^7.0.3", "css-prefers-color-scheme": "^10.0.0", - "cssdb": "^8.3.0", + "cssdb": "^8.4.2", "postcss-attribute-case-insensitive": "^7.0.1", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^7.0.10", + "postcss-color-functional-notation": "^7.0.12", "postcss-color-hex-alpha": "^10.0.0", "postcss-color-rebeccapurple": "^10.0.0", "postcss-custom-media": "^11.0.6", - "postcss-custom-properties": "^14.0.5", + "postcss-custom-properties": "^14.0.6", "postcss-custom-selectors": "^8.0.5", "postcss-dir-pseudo-class": "^9.0.1", - "postcss-double-position-gradients": "^6.0.2", + "postcss-double-position-gradients": "^6.0.4", "postcss-focus-visible": "^10.0.1", "postcss-focus-within": "^9.0.1", "postcss-font-variant": "^5.0.0", "postcss-gap-properties": "^6.0.0", "postcss-image-set-function": "^7.0.0", - "postcss-lab-function": "^7.0.10", + "postcss-lab-function": "^7.0.12", "postcss-logical": "^8.1.0", - "postcss-nesting": "^13.0.1", + "postcss-nesting": "^13.0.2", "postcss-opacity-percentage": "^3.0.0", "postcss-overflow-shorthand": "^6.0.0", "postcss-page-break": "^3.0.4", @@ -15275,9 +15700,9 @@ } }, "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -15588,9 +16013,9 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-view-lite": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.4.1.tgz", - "integrity": "sha512-fwFYknRIBxjbFm0kBDrzgBy1xa5tDg2LyXXBepC5f1b+MY3BUClMCsvanMPn089JbV1Eg3nZcrp0VCuH43aXnA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.5.0.tgz", + "integrity": "sha512-tk7o7QG9oYyELWHL8xiMQ8x4WzjCzbWNyig3uexmkLb54r8jO0yH3WCWx8UZS0c49eSA4QUmG5caiRJ8fAn58g==", "license": "MIT", "engines": { "node": ">=18" @@ -15692,6 +16117,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -15770,9 +16196,9 @@ "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -15787,17 +16213,17 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", "license": "MIT", "dependencies": { "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", + "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", + "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "unicode-match-property-value-ecmascript": "^2.2.1" }, "engines": { "node": ">=4" @@ -15835,29 +16261,17 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~3.0.2" + "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/rehype-parse": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-7.0.1.tgz", @@ -16381,20 +16795,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rtlcss": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", @@ -16413,6 +16813,18 @@ "node": ">=12.0.0" } }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -16482,9 +16894,9 @@ "license": "Apache-2.0" }, "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -16493,7 +16905,7 @@ "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -16612,12 +17024,6 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/send/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -16847,23 +17253,81 @@ } }, "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -17038,9 +17502,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -17380,6 +17844,19 @@ "node": ">= 10" } }, + "node_modules/swr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz", + "integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -17389,9 +17866,9 @@ } }, "node_modules/tar-fs": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", - "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -17547,6 +18024,34 @@ "b4a": "^1.6.4" } }, + "node_modules/thingies": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", + "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/throttleit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", + "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -17659,6 +18164,22 @@ "node": ">=6" } }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -17798,18 +18319,18 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "license": "MIT", "engines": { "node": ">=4" @@ -18180,6 +18701,15 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18386,44 +18916,50 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", "license": "MIT", "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, "node_modules/webpack-dev-middleware/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { "node": ">= 0.6" @@ -18439,54 +18975,52 @@ } }, "node_modules/webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", - "license": "MIT", - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/express-serve-static-core": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", + "express": "^4.21.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", + "http-proxy-middleware": "^2.0.9", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "webpack": "^5.0.0" }, "peerDependenciesMeta": { "webpack": { @@ -18497,10 +19031,40 @@ } } }, + "node_modules/webpack-dev-server/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -18847,6 +19411,36 @@ } } }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wsl-utils/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xdg-basedir": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", @@ -18896,6 +19490,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/site/package.json b/site/package.json index c44366ecd4..a1220d6527 100644 --- a/site/package.json +++ b/site/package.json @@ -18,9 +18,9 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.8.0", - "@docusaurus/plugin-ideal-image": "^3.8.0", - "@docusaurus/preset-classic": "^3.8.0", + "@docusaurus/core": "^3.9.1", + "@docusaurus/plugin-ideal-image": "^3.9.1", + "@docusaurus/preset-classic": "^3.9.1", "@mdx-js/react": "^3.0.0", "@types/react": "^18.3.7", "clsx": "^2.0.0", From fecdf43bbfe1def1b7806f9fd58b248ec8a05b37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:58:30 -0400 Subject: [PATCH 145/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.87.3 to 1.88.4 (#1898) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.87.3 to 1.88.4.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.87.3&new-version=1.88.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index c680f11e9c..3063af1392 100644 --- a/go.mod +++ b/go.mod @@ -48,14 +48,14 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 // indirect @@ -272,10 +272,10 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.38.3 + github.com/aws/aws-sdk-go-v2 v1.39.2 github.com/aws/aws-sdk-go-v2/config v1.31.6 github.com/aws/aws-sdk-go-v2/credentials v1.18.10 - github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 + github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index 3d324a19c7..04eef7c9b8 100644 --- a/go.sum +++ b/go.sum @@ -244,8 +244,8 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.38.3 h1:B6cV4oxnMs45fql4yRH+/Po/YU+597zgWqvDpYMturk= -github.com/aws/aws-sdk-go-v2 v1.38.3/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= +github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I= +github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00= github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= @@ -256,30 +256,30 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 h1:wbjnrrMnKew78/juW7I2BtK github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6/go.mod h1:AtiqqNrDioJXuUgz3+3T0mBWN7Hro2n9wll2zRUc0ww= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 h1:uF68eJA6+S9iVr9WgX1NaRGyQ/6MdIyc4JNUo6TN1FA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6/go.mod h1:qlPeVZCGPiobx8wb1ft0GHT5l+dc6ldnwInDFaMvC7Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 h1:pa1DEC6JoI0zduhZePp3zmhWvk/xxm4NB8Hy/Tlsgos= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6/go.mod h1:gxEjPebnhWGJoaDdtDkA0JX46VRg1wcTHYe63OfX5pE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 h1:R0tNFJqfjHL3900cqhXuwQ+1K4G0xc9Yf8EDbFXCKEw= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6/go.mod h1:y/7sDdu+aJvPtGXr4xYosdpq9a6T9Z0jkXfugmti0rI= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 h1:w9LnHqTq8MEdlnyhV4Bwfizd65lfNCNgdlNC6mM5paE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9/go.mod h1:LGEP6EK4nj+bwWNdrvX/FnDTFowdBNwcSPuZu/ouFys= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 h1:hncKj/4gR+TPauZgTAsxOxNcvBayhUlYZ6LO/BYiQ30= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6/go.mod h1:OiIh45tp6HdJDDJGnja0mw8ihQGz3VGrUflLqSL0SmM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 h1:LHS1YAIJXJ4K9zS+1d/xa9JAA9sL2QyXIQCQFQW/X08= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6/go.mod h1:c9PCiTEuh0wQID5/KqA32J+HAgZxN9tOGXKCiYJjTZI= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 h1:nEXUSAwyUfLTgnc9cxlDWy637qsq4UWwp3sNAfl0Z3Y= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6/go.mod h1:HGzIULx4Ge3Do2V0FaiYKcyKzOqwrhUZgCI77NisswQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0 h1:X0FveUndcZ3lKbSpIC6rMYGRiQTcUVRNH6X4yYtIrlU= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0/go.mod h1:IWjQYlqw4EX9jw2g3qnEPPWvCE6bS8fKzhMed1OK7c8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 h1:wuZ5uW2uhJR63zwNlqWH2W4aL4ZjeJP3o92/W+odDY4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9/go.mod h1:/G58M2fGszCrOzvJUkDdY8O9kycodunH4VdT5oBAqls= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 h1:ETkfWcXP2KNPLecaDa++5bsQhCRa5M5sLUJa5DWYIIg= -github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3/go.mod h1:+/3ZTqoYb3Ur7DObD00tarKMLMuKg8iqz5CHEanqTnw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4 h1:mUI3b885qJgfqKDUSj6RgbRqLdX0wGmg8ruM03zNfQA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4/go.mod h1:6v8ukAxc7z4x4oBjGUsLnH7KGLY9Uhcgij19UJNkiMg= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 h1:8OLZnVJPvjnrxEwHFg9hVUof/P4sibH+Ea4KKuqAGSg= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1/go.mod h1:27M3BpVi0C02UiQh1w9nsBEit6pLhlaH3NHna6WUbDE= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 h1:gKWSTnqudpo8dAxqBqZnDoDWCiEh/40FziUjr/mo6uA= From 3cf29d30395b6734956846a31ef2ac1dc95f2af8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:58:44 -0400 Subject: [PATCH 146/448] deps: bump golang.org/x/sys from 0.35.0 to 0.37.0 (#1899) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.35.0 to 0.37.0.
Commits
  • 1edeebe unix: mkall.sh: fail if docker build failed
  • ecada54 unix: use slices.{Equal,Sort} in tests
  • 5e63aa5 windows: export O_FILE_FLAG_* to be used in os.OpenFile on windows
  • 033906b unix: add (*CPUSet).Fill helper to enable all CPUs
  • 6be6c58 windows: add FlushConsoleInputBuffer and GetNumberOfConsoleInputEvents
  • 32e2038 unix: use Go 1.21+ clear built-in
  • 137f2ed sys: add support for NetBSD getvfsstat
  • b06ce05 windows: add FILE_ZERO_DATA_INFORMATION
  • 689cc11 unix: fix Listen on solaris
  • a4712b9 plan9: drop go version tags for unsupported versions
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sys&package-manager=go_modules&previous-version=0.35.0&new-version=0.37.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3063af1392..99a525b9a4 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.17.0 - golang.org/x/sys v0.35.0 + golang.org/x/sys v0.37.0 golang.org/x/term v0.34.0 // indirect google.golang.org/protobuf v1.36.8 gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 04eef7c9b8..0c03fc9c87 100644 --- a/go.sum +++ b/go.sum @@ -1780,8 +1780,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From 6edfe7e3e98ef5e08d842d6f5e5348f64deaf1c7 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:26:21 +0100 Subject: [PATCH 147/448] chore(shell): Add sysctl and doc (#1901) # Description **Add sysctl support to retina shell for kernel parameter inspection** This PR adds `sysctl` functionality to the retina shell by installing the `procps-ng` package in the shell Docker image and documenting its usage in the troubleshooting guide. The `sysctl` tool is essential for network troubleshooting as it allows users to inspect and modify kernel networking parameters such as IP forwarding, TCP congestion control, buffer sizes, and other network-related settings. The documentation includes clear examples of common networking parameter queries and explains the important distinction between viewing kernel parameters in the container context versus the node context (requiring chroot /host for node-level parameters). This enhancement provides network administrators and developers with a critical tool for diagnosing kernel-level networking issues directly from the retina shell environment. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- docs/06-Troubleshooting/shell.md | 33 ++++++++++++++++++++++++++++++++ shell/Dockerfile | 1 + 2 files changed, 34 insertions(+) diff --git a/docs/06-Troubleshooting/shell.md b/docs/06-Troubleshooting/shell.md index 9f12bd95e4..3951feb5f2 100644 --- a/docs/06-Troubleshooting/shell.md +++ b/docs/06-Troubleshooting/shell.md @@ -184,6 +184,39 @@ pwru -h pwru "tcp and (src port 8080 or dst port 8080)" ``` +## [sysctl](https://man7.org/linux/man-pages/man8/sysctl.8.html) + +Tool for viewing and modifying kernel parameters at runtime. `sysctl` is useful for network troubleshooting as it allows you to inspect and tune various kernel networking settings such as IP forwarding, TCP congestion control, buffer sizes, and other network-related parameters. + +For viewing kernel parameters, no special capabilities are required: + +```shell +kubectl retina shell +``` + +For modifying kernel parameters, you may need the `SYS_ADMIN` capability and/or `chroot` to the host filesystem depending on the parameter: + +```shell +kubectl retina shell --capabilities=SYS_ADMIN --mount-host-filesystem +``` + +You can then run, for example: + +```shell +# View kernel parameters +sysctl net.ipv4.ip_forward +sysctl -a | grep tcp_congestion +sysctl net.core.rmem_max + +# View all networking-related parameters +sysctl -a | grep net + +# Modify parameters (may require chroot /host) +sysctl -w net.ipv4.ip_forward=1 +``` + +>NOTE: `sysctl` shows different kernel parameters depending on whether you're running in the container context or the node context. To view/modify the actual node's kernel parameters, use `chroot /host` after mounting the host filesystem. Running `sysctl` without `chroot` shows the container's view, which may have limited or different parameters. + ## [bpftool](https://github.com/libbpf/bpftool) Allows you to list, dump, load BPF programs, etc. Reference utility to quickly inspect and manage BPF objects on your system, to manipulate BPF object files, or to perform various other BPF-related tasks. diff --git a/shell/Dockerfile b/shell/Dockerfile index 1374511d2e..74f1716259 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -20,6 +20,7 @@ RUN tdnf install -y \ nmap \ nmap-ncat \ openssh \ + procps-ng \ sysstat \ socat \ tcpdump \ From 62de7989da1ac3c01f288633b9644e3d21f34ab8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:04:19 -0400 Subject: [PATCH 148/448] deps: bump actions/setup-node from 5 to 6 (#1902) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6.
Release notes

Sourced from actions/setup-node's releases.

v6.0.0

What's Changed

Breaking Changes

Dependency Upgrades

Full Changelog: https://github.com/actions/setup-node/compare/v5...v6.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 6f04ba3755..5bf0f8d9e4 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-node@v5 + - uses: actions/setup-node@v6 with: node-version: 20 - name: build From 8185419a780caa531fd452d6976fedbacb4f87f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:05:48 -0400 Subject: [PATCH 149/448] deps: bump google.golang.org/protobuf from 1.36.8 to 1.36.10 (#1903) Bumps google.golang.org/protobuf from 1.36.8 to 1.36.10. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/protobuf&package-manager=go_modules&previous-version=1.36.8&new-version=1.36.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 99a525b9a4..9b5eb80053 100644 --- a/go.mod +++ b/go.mod @@ -245,7 +245,7 @@ require ( golang.org/x/sync v0.17.0 golang.org/x/sys v0.37.0 golang.org/x/term v0.34.0 // indirect - google.golang.org/protobuf v1.36.8 + google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 k8s.io/apimachinery v0.32.4 diff --git a/go.sum b/go.sum index 0c03fc9c87..24ad6e4b04 100644 --- a/go.sum +++ b/go.sum @@ -1894,8 +1894,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= -google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= From e419b3cf998e5f82e06b3c6092657dbe0a152dd7 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Tue, 21 Oct 2025 14:09:26 +0100 Subject: [PATCH 150/448] fix: download windows (#1905) # Description Retina captures were using a Linux container for the downloading, and had no counterpart for Windows based clusters. This PR adds in support for Windows and its different flavours of ltsc. ## Related Issue https://github.com/microsoft/retina/issues/1834 ## Relate PR https://github.com/microsoft/retina/pull/1853 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Co-authored-by: Kamil --- cli/cmd/capture/download.go | 359 ++++++--- cli/cmd/capture/download_test.go | 821 +++++++++++++++++++++ pkg/capture/constants/job_specification.go | 6 +- pkg/capture/utils/label.go | 7 + 4 files changed, 1087 insertions(+), 106 deletions(-) create mode 100644 cli/cmd/capture/download_test.go diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index 5c0a74322c..6443857270 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -6,6 +6,7 @@ package capture import ( "bytes" "context" + "errors" "fmt" "io" "net/url" @@ -19,8 +20,8 @@ import ( "github.com/Azure/azure-sdk-for-go/storage" retinacmd "github.com/microsoft/retina/cli/cmd" captureConstants "github.com/microsoft/retina/pkg/capture/constants" + captureUtils "github.com/microsoft/retina/pkg/capture/utils" captureLabels "github.com/microsoft/retina/pkg/label" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" "go.uber.org/zap" @@ -35,14 +36,39 @@ import ( "k8s.io/kubectl/pkg/util/templates" ) +// NodeOS represents the operating system of a Kubernetes node +type NodeOS *int + +const ( + LinuxOS = 0 + WindowsOS = 1 +) + +var ( + Linux NodeOS = &[]int{LinuxOS}[0] + Windows NodeOS = &[]int{WindowsOS}[0] +) + const ( DefaultOutputPath = "./" ) var ( - blobURL string - captureName string - outputPath string + blobURL string + ErrCreateDirectory = errors.New("failed to create directory") + ErrGetNodeInfo = errors.New("failed to get node information") + ErrWriteFileToHost = errors.New("failed to write file to host") + ErrObtainPodList = errors.New("failed to obtain list of pods") + ErrExecFileDownload = errors.New("failed to exec file download in container") + ErrCreateDownloadPod = errors.New("failed to create download pod") + ErrGetDownloadPod = errors.New("failed to get download pod") + ErrCheckFileExistence = errors.New("failed to check file existence") + ErrCreateExecutor = errors.New("failed to create executor") + ErrExecCommand = errors.New("failed to exec command") + ErrCreateOutputDir = errors.New("failed to create output directory") + ErrNoBlobsFound = errors.New("no blobs found with prefix") + captureName string + outputPath string ) var ( @@ -52,8 +78,116 @@ var ( ErrFileNotAccessible = errors.New("file does not exist or is not readable") ErrEmptyDownloadOutput = errors.New("download command produced no output") ErrFailedToCreateDownloadPod = errors.New("failed to create download pod") + ErrUnsupportedNodeOS = errors.New("unsupported node operating system") ) +// DownloadCmd holds all OS-specific commands and configurations +type DownloadCmd struct { + ContainerImage string + SrcFilePath string + MountPath string + KeepAliveCommand []string + FileCheckCommand []string + FileReadCommand []string +} + +// DownloadService encapsulates the download functionality and shared dependencies +type DownloadService struct { + kubeClient kubernetes.Interface + config *rest.Config + namespace string +} + +// NewDownloadService creates a new download service with shared dependencies +func NewDownloadService(kubeClient kubernetes.Interface, config *rest.Config, namespace string) *DownloadService { + return &DownloadService{ + kubeClient: kubeClient, + config: config, + namespace: namespace, + } +} + +func getDownloadCmd(node *corev1.Node, hostPath, fileName string) (*DownloadCmd, error) { + nodeOS, err := getNodeOS(node) + if err != nil { + return nil, err + } + + if nodeOS == nil { + return nil, ErrUnsupportedNodeOS + } + + switch *nodeOS { + case WindowsOS: + srcFilePath := "C:\\host" + strings.ReplaceAll(hostPath, "/", "\\") + "\\" + fileName + ".tar.gz" + mountPath := "C:\\host" + strings.ReplaceAll(hostPath, "/", "\\") + return &DownloadCmd{ + ContainerImage: getWindowsContainerImage(node), + SrcFilePath: srcFilePath, + MountPath: mountPath, + KeepAliveCommand: []string{"cmd", "/c", "echo Download pod ready & ping -n 3601 127.0.0.1 > nul"}, + FileCheckCommand: []string{"cmd", "/c", fmt.Sprintf("if exist %s echo FILE_EXISTS", srcFilePath)}, + FileReadCommand: []string{"cmd", "/c", "type", srcFilePath}, + }, nil + case LinuxOS: + srcFilePath := "/" + filepath.Join("host", hostPath, fileName) + ".tar.gz" + mountPath := "/" + filepath.Join("host", hostPath) + return &DownloadCmd{ + ContainerImage: "mcr.microsoft.com/azurelinux/busybox:1.36", + SrcFilePath: srcFilePath, + MountPath: mountPath, + KeepAliveCommand: []string{"sh", "-c", "echo 'Download pod ready'; sleep 3600"}, + FileCheckCommand: []string{"sh", "-c", fmt.Sprintf("if [ -r %q ]; then echo 'FILE_EXISTS'; fi", srcFilePath)}, + FileReadCommand: []string{"cat", srcFilePath}, + }, nil + default: + return nil, ErrUnsupportedNodeOS + } +} + +func getNodeOS(node *corev1.Node) (NodeOS, error) { + nodeOS := strings.ToLower(node.Status.NodeInfo.OperatingSystem) + + if strings.Contains(nodeOS, "windows") { + retinacmd.Logger.Info("Detected node OS: Windows", zap.String("node", node.Name), zap.String("os", node.Status.NodeInfo.OperatingSystem)) + return Windows, nil + } + + if strings.Contains(nodeOS, "linux") { + retinacmd.Logger.Info("Detected node OS: Linux", zap.String("node", node.Name), zap.String("os", node.Status.NodeInfo.OperatingSystem)) + return Linux, nil + } + + return nil, fmt.Errorf("unsupported operating system: %s: %w", node.Status.NodeInfo.OperatingSystem, ErrUnsupportedNodeOS) +} + +// Detects the Windows LTSC version and returns the appropriate nanoserver image +func getWindowsContainerImage(node *corev1.Node) string { + osImage := strings.ToLower(node.Status.NodeInfo.OSImage) + + var suffix string + switch { + case strings.Contains(osImage, "2025"): + suffix = "ltsc2025" + case strings.Contains(osImage, "2022"): + suffix = "ltsc2022" + case strings.Contains(osImage, "2019"): + suffix = "ltsc2019" + case strings.Contains(osImage, "2016"): + suffix = "ltsc2016" + default: + retinacmd.Logger.Warn("Could not determine Windows LTSC version, defaulting to ltsc2022", + zap.String("node", node.Name), + zap.String("osImage", osImage)) + suffix = "ltsc2022" + } + + containerImage := "mcr.microsoft.com/windows/nanoserver:" + suffix + retinacmd.Logger.Info("Selected Windows container image", zap.String("image", containerImage)) + + return containerImage +} + var downloadExample = templates.Examples(i18n.T(` # List Retina capture jobs kubectl retina capture list @@ -69,25 +203,28 @@ var downloadExample = templates.Examples(i18n.T(` `)) func downloadFromCluster(ctx context.Context, config *rest.Config, namespace string) error { + fmt.Println("Downloading capture: ", captureName) kubeClient, err := kubernetes.NewForConfig(config) if err != nil { - return errors.Wrap(err, "failed to initialize k8s client") + return fmt.Errorf("failed to initialize k8s client: %w", err) } + downloadService := NewDownloadService(kubeClient, config, namespace) + pods, err := getCapturePods(ctx, kubeClient, captureName, namespace) if err != nil { - return errors.Wrap(err, "failed to obtain capture pod") + return fmt.Errorf("failed to obtain capture pod: %w", err) } err = os.MkdirAll(filepath.Join(outputPath, captureName), 0o775) if err != nil { - return fmt.Errorf("failed to create directory: %w", err) + return errors.Join(ErrCreateDirectory, err) } for i := range pods.Items { pod := pods.Items[i] if pod.Status.Phase != corev1.PodSucceeded { - return errors.Wrap(ErrNoPodFound, captureName) + return fmt.Errorf("%s: %w", captureName, ErrNoPodFound) } nodeName := pod.Spec.NodeName @@ -100,84 +237,111 @@ func downloadFromCluster(ctx context.Context, config *rest.Config, namespace str return errors.New("cannot obtain capture file name from pod annotations") } - srcFilePath := "/" + filepath.Join("host", hostPath, fileName) + ".tar.gz" - fmt.Println("\nFile to be downloaded: ", srcFilePath) - downloadPod, err := createDownloadPod(ctx, kubeClient, namespace, nodeName, hostPath, captureName) + err = downloadService.DownloadFile(ctx, nodeName, hostPath, fileName, captureName) if err != nil { return err } + } - fmt.Println("Obtaining file...") - exec, err := createDownloadExec(ctx, kubeClient, config, downloadPod, srcFilePath) - if err != nil { - return err - } + return nil +} - var outBuf, errBuf bytes.Buffer - streamOpts := remotecommand.StreamOptions{ - Stdout: &outBuf, - Stderr: &errBuf, - } - if err = exec.StreamWithContext(ctx, streamOpts); err != nil { - return fmt.Errorf("failed to exec in download container: %w", err) - } +// DownloadFile downloads a capture file from a specific node +func (ds *DownloadService) DownloadFile(ctx context.Context, nodeName, hostPath, fileName, captureName string) error { + node, err := ds.kubeClient.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{}) + if err != nil { + return errors.Join(ErrGetNodeInfo, err) + } - if outBuf.Len() == 0 { - return errors.Wrap(ErrEmptyDownloadOutput, errBuf.String()) - } + downloadCmd, err := getDownloadCmd(node, hostPath, fileName) + if err != nil { + return err + } - outputFile := filepath.Join(outputPath, captureName, fileName+".tar.gz") - fmt.Printf("Bytes retrieved: %d\n", outBuf.Len()) + fmt.Println("File to be downloaded: ", downloadCmd.SrcFilePath) + downloadPod, err := ds.createDownloadPod(ctx, nodeName, hostPath, captureName, downloadCmd) + if err != nil { + return err + } - err = os.WriteFile(outputFile, outBuf.Bytes(), 0o600) - if err != nil { - return fmt.Errorf("failed to write file to host: %w", err) - } + fileExists, err := ds.verifyFileExists(ctx, downloadPod, downloadCmd) + if err != nil || !fileExists { + return err + } - fmt.Println("File written to: ", outputFile) + fmt.Println("Obtaining file...") + fileContent, err := ds.executeFileDownload(ctx, downloadPod, downloadCmd) + if err != nil { + return err + } - err = kubeClient.CoreV1().Pods(namespace).Delete(ctx, downloadPod.Name, metav1.DeleteOptions{}) - if err != nil { - retinacmd.Logger.Warn("Failed to clean up debug pod", zap.String("name", downloadPod.Name), zap.Error(err)) - } + outputFile := filepath.Join(outputPath, captureName, fileName+".tar.gz") + fmt.Printf("Bytes retrieved: %d\n", len(fileContent)) + + err = os.WriteFile(outputFile, fileContent, 0o600) + if err != nil { + return errors.Join(ErrWriteFileToHost, err) } + fmt.Printf("File written to: %s\n", outputFile) + + // Ensure cleanup + err = ds.kubeClient.CoreV1().Pods(ds.namespace).Delete(ctx, downloadPod.Name, metav1.DeleteOptions{}) + if err != nil { + retinacmd.Logger.Warn("Failed to clean up debug pod", zap.String("name", downloadPod.Name), zap.Error(err)) + } return nil } -func getCapturePods(ctx context.Context, kubeClient *kubernetes.Clientset, captureName, namespace string) (*corev1.PodList, error) { +func getCapturePods(ctx context.Context, kubeClient kubernetes.Interface, captureName, namespace string) (*corev1.PodList, error) { pods, err := kubeClient.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{ LabelSelector: captureLabels.CaptureNameLabel + "=" + captureName, }) if err != nil { - return &corev1.PodList{}, fmt.Errorf("failed to obtain list of pods: %w", err) + return &corev1.PodList{}, errors.Join(ErrObtainPodList, err) } if len(pods.Items) == 0 { - return &corev1.PodList{}, errors.Wrap(ErrNoPodFound, captureName) + return &corev1.PodList{}, fmt.Errorf("%s: %w", captureName, ErrNoPodFound) } return pods, nil } -func createDownloadPod(ctx context.Context, kubeClient *kubernetes.Clientset, namespace, nodeName, hostPath, captureName string) (*corev1.Pod, error) { +// executeFileDownload downloads the file content from the pod +func (ds *DownloadService) executeFileDownload(ctx context.Context, pod *corev1.Pod, downloadCmd *DownloadCmd) ([]byte, error) { + content, err := ds.createDownloadExec(ctx, pod, downloadCmd.FileReadCommand) + if err != nil { + return nil, errors.Join(ErrExecFileDownload, err) + } + + if content == "" { + return nil, ErrEmptyDownloadOutput + } + + return []byte(content), nil +} + +// createDownloadPod creates a pod for downloading files from the host +func (ds *DownloadService) createDownloadPod(ctx context.Context, nodeName, hostPath, captureName string, downloadCmd *DownloadCmd) (*corev1.Pod, error) { podName := captureName + "-download-" + rand.String(5) podSpec := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: podName, - Namespace: namespace, + Namespace: ds.namespace, + Labels: captureUtils.GetDownloadLabelsFromCaptureName(captureName), }, Spec: corev1.PodSpec{ NodeName: nodeName, Containers: []corev1.Container{ { - Name: "download", - Image: "mcr.microsoft.com/azurelinux/busybox:1.36", - Command: []string{"sh", "-c", "echo 'Download pod ready'; sleep 3600"}, + Name: captureConstants.DownloadContainerName, + Image: downloadCmd.ContainerImage, + Command: downloadCmd.KeepAliveCommand, VolumeMounts: []corev1.VolumeMount{ { Name: "host-mount", - MountPath: "/" + filepath.Join("host", hostPath), + MountPath: downloadCmd.MountPath, }, }, }, @@ -197,64 +361,46 @@ func createDownloadPod(ctx context.Context, kubeClient *kubernetes.Clientset, na } fmt.Printf("Creating download pod: %s\n", podName) - _, err := kubeClient.CoreV1().Pods(namespace).Create(ctx, podSpec, metav1.CreateOptions{}) + _, err := ds.kubeClient.CoreV1().Pods(ds.namespace).Create(ctx, podSpec, metav1.CreateOptions{}) if err != nil { - return nil, fmt.Errorf("failed to create download pod: %w", err) + return nil, errors.Join(ErrCreateDownloadPod, err) } + return ds.waitForPodReady(ctx, podName) +} + +// waitForPodReady waits for the pod to be in running state +func (ds *DownloadService) waitForPodReady(ctx context.Context, podName string) (*corev1.Pod, error) { timeout := time.After(30 * time.Second) ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() - var pod *corev1.Pod + for { select { case <-timeout: - return nil, errors.Wrap(ErrFailedToCreateDownloadPod, "timeout waiting for download pod to become ready") + return nil, fmt.Errorf("timeout waiting for download pod to become ready: %w", ErrFailedToCreateDownloadPod) case <-ticker.C: - pod, err = kubeClient.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{}) + pod, err := ds.kubeClient.CoreV1().Pods(ds.namespace).Get(ctx, podName, metav1.GetOptions{}) if err != nil { - return nil, fmt.Errorf("failed to get download pod: %w", err) + return nil, errors.Join(ErrGetDownloadPod, err) } if pod.Status.Phase == corev1.PodRunning { return pod, nil } if pod.Status.Phase == corev1.PodFailed { - return nil, errors.Wrap(ErrFailedToCreateDownloadPod, "download pod failed to spin up successfully") + return nil, fmt.Errorf("download pod failed to spin up successfully: %w", ErrFailedToCreateDownloadPod) } } } } -func verifyFileExists(ctx context.Context, kubeClient *kubernetes.Clientset, config *rest.Config, pod *corev1.Pod, filePath string) (bool, error) { +// verifyFileExists checks if the target file exists and is accessible +func (ds *DownloadService) verifyFileExists(ctx context.Context, pod *corev1.Pod, downloadCmd *DownloadCmd) (bool, error) { maxAttempts := 3 for attempt := 1; attempt <= maxAttempts; attempt++ { - checkReq := kubeClient.CoreV1().RESTClient().Post(). - Resource("pods"). - Name(pod.Name). - Namespace(pod.Namespace). - SubResource("exec"). - VersionedParams(&corev1.PodExecOptions{ - Container: "download", - Command: []string{"sh", "-c", fmt.Sprintf("if [ -r %q ]; then echo 'FILE_EXISTS'; fi", filePath)}, - Stdout: true, - Stderr: true, - }, scheme.ParameterCodec) - - checkExec, err := remotecommand.NewSPDYExecutor(config, "POST", checkReq.URL()) + checkOutput, err := ds.createDownloadExec(ctx, pod, downloadCmd.FileCheckCommand) if err != nil { - if attempt == maxAttempts { - return false, fmt.Errorf("failed to create check executor after %d attempts: %w", attempt, err) - } - time.Sleep(time.Duration(attempt*2) * time.Second) - continue - } - - var checkBuf bytes.Buffer - if err = checkExec.StreamWithContext(ctx, remotecommand.StreamOptions{ - Stdout: &checkBuf, - Stderr: &checkBuf, - }); err != nil { if attempt == maxAttempts { return false, fmt.Errorf("failed to check file existence after %d attempts: %w", attempt, err) } @@ -262,8 +408,6 @@ func verifyFileExists(ctx context.Context, kubeClient *kubernetes.Clientset, con continue } - checkOutput := checkBuf.String() - if strings.Contains(checkOutput, "FILE_EXISTS") { return true, nil } @@ -271,45 +415,52 @@ func verifyFileExists(ctx context.Context, kubeClient *kubernetes.Clientset, con time.Sleep(time.Duration(attempt*2) * time.Second) } - return false, errors.Wrap(ErrFileNotAccessible, filePath) + return false, fmt.Errorf("%s: %w", downloadCmd.SrcFilePath, ErrFileNotAccessible) } -func createDownloadExec(ctx context.Context, kubeClient *kubernetes.Clientset, config *rest.Config, pod *corev1.Pod, srcFilePath string) (remotecommand.Executor, error) { - fileExists, err := verifyFileExists(ctx, kubeClient, config, pod, srcFilePath) - if err != nil || !fileExists { - return nil, err - } - - req := kubeClient.CoreV1().RESTClient().Post(). +// createDownloadExec executes a command in the pod and returns the output +func (ds *DownloadService) createDownloadExec(ctx context.Context, pod *corev1.Pod, command []string) (string, error) { + req := ds.kubeClient.CoreV1().RESTClient().Post(). Resource("pods"). Name(pod.Name). Namespace(pod.Namespace). SubResource("exec"). VersionedParams(&corev1.PodExecOptions{ - Container: "download", - Command: []string{"cat", srcFilePath}, + Container: captureConstants.DownloadContainerName, + Command: command, Stdout: true, Stderr: true, }, scheme.ParameterCodec) - exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL()) + exec, err := remotecommand.NewSPDYExecutor(ds.config, "POST", req.URL()) if err != nil { - return nil, fmt.Errorf("failed to create executor: %w", err) + return "", errors.Join(ErrCreateExecutor, err) } - return exec, nil + + var outBuf, errBuf bytes.Buffer + streamOpts := remotecommand.StreamOptions{ + Stdout: &outBuf, + Stderr: &errBuf, + } + + if err = exec.StreamWithContext(ctx, streamOpts); err != nil { + return "", fmt.Errorf("failed to exec command (stderr: %s): %w", errBuf.String(), err) + } + + return outBuf.String(), nil } func downloadFromBlob() error { u, err := url.Parse(blobURL) if err != nil { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Wrapf(err, "failed to parse SAS URL %s", blobURL) + return fmt.Errorf("failed to parse SAS URL %s: %w", blobURL, err) } b, err := storage.NewAccountSASClientFromEndpointToken(u.String(), u.Query().Encode()) if err != nil { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Wrap(err, "failed to create storage account client") + return fmt.Errorf("failed to create storage account client: %w", err) } blobService := b.GetBlobService() @@ -321,17 +472,17 @@ func downloadFromBlob() error { blobList, err := blobService.GetContainerReference(containerName).ListBlobs(params) if err != nil { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Wrap(err, "failed to list blobstore ") + return fmt.Errorf("failed to list blobstore: %w", err) } if len(blobList.Blobs) == 0 { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Errorf("no blobs found with prefix: %s", *opts.Name) + return fmt.Errorf("%w: %s", ErrNoBlobsFound, *opts.Name) } err = os.MkdirAll(outputPath, 0o775) if err != nil { - return fmt.Errorf("failed to create output directory: %w", err) + return errors.Join(ErrCreateOutputDir, err) } for i := range blobList.Blobs { @@ -340,21 +491,21 @@ func downloadFromBlob() error { readCloser, err := blobRef.Get(&storage.GetBlobOptions{}) if err != nil { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Wrap(err, "failed to read from blobstore") + return fmt.Errorf("failed to read from blobstore: %w", err) } blobData, err := io.ReadAll(readCloser) readCloser.Close() if err != nil { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Wrap(err, "failed to obtain blob from blobstore") + return fmt.Errorf("failed to obtain blob from blobstore: %w", err) } outputFile := filepath.Join(outputPath, blob.Name) err = os.WriteFile(outputFile, blobData, 0o600) if err != nil { retinacmd.Logger.Error("err: ", zap.Error(err)) - return errors.Wrap(err, "failed to write file") + return fmt.Errorf("failed to write file: %w", err) } fmt.Println("Downloaded: ", outputFile) @@ -372,7 +523,7 @@ func NewDownloadSubCommand() *cobra.Command { kubeConfig, err := opts.ToRESTConfig() if err != nil { - return errors.Wrap(err, "failed to compose k8s rest config") + return fmt.Errorf("failed to compose k8s rest config: %w", err) } ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM) diff --git a/cli/cmd/capture/download_test.go b/cli/cmd/capture/download_test.go new file mode 100644 index 0000000000..dbc2180789 --- /dev/null +++ b/cli/cmd/capture/download_test.go @@ -0,0 +1,821 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + + "github.com/spf13/cobra" + + captureConstants "github.com/microsoft/retina/pkg/capture/constants" + "github.com/microsoft/retina/pkg/label" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" + clienttesting "k8s.io/client-go/testing" +) + +const ( + testCapture = "test-capture" + testFile = "test-file" + cmdCommand = "cmd" + shellCommand = "sh" +) + +func NewLinuxNode(name string) *corev1.Node { + return &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "kubernetes.io/hostname": name, + }, + }, + Status: corev1.NodeStatus{ + NodeInfo: corev1.NodeSystemInfo{ + OperatingSystem: "linux", + OSImage: "Ubuntu 20.04 LTS", + }, + }, + } +} + +func NewWindowsNode(name string) *corev1.Node { + return &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "kubernetes.io/hostname": name, + }, + }, + Status: corev1.NodeStatus{ + NodeInfo: corev1.NodeSystemInfo{ + OperatingSystem: "windows", + OSImage: "Windows Server 2022 Datacenter", + }, + }, + } +} + +func NewDownloadNamespace(name string) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } +} + +func NewCapturePodsWithStatus(captureName, namespace, nodeName string, status corev1.PodPhase) *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: captureName + "-" + nodeName, + Namespace: namespace, + Labels: map[string]string{ + label.CaptureNameLabel: captureName, + }, + Annotations: map[string]string{ + captureConstants.CaptureHostPathAnnotationKey: "/tmp/captures", + captureConstants.CaptureFilenameAnnotationKey: "capture-" + nodeName, + }, + }, + Spec: corev1.PodSpec{ + NodeName: nodeName, + }, + Status: corev1.PodStatus{ + Phase: status, + }, + } +} + +func newDownloadKubeClient(objects []runtime.Object) *fake.Clientset { + if objects == nil { + objects = []runtime.Object{ + NewLinuxNode("linux-node-1"), + NewWindowsNode("windows-node-1"), + NewDownloadNamespace("default"), + NewDownloadNamespace("capture-test"), + } + } + + kubeClient := fake.NewClientset(objects...) + + // Mock pod creation for download pods + kubeClient.PrependReactor("create", "pods", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction, ok := action.(clienttesting.CreateAction) + if !ok { + return false, nil, fmt.Errorf("%w: expected CreateAction", ErrCreateDownloadPod) + } + pod := createAction.GetObject().(*corev1.Pod) + + // Simulate pod running after creation + pod.Status.Phase = corev1.PodRunning + return false, pod, nil + }) + + return kubeClient +} + +func TestDownloadFromCluster(t *testing.T) { + tempDir := t.TempDir() + + // Set global variables for testing + originalCaptureName := captureName + originalOutputPath := outputPath + captureName = testCapture + outputPath = tempDir + defer func() { + captureName = originalCaptureName + outputPath = originalOutputPath + }() + + testCases := []struct { + name string + namespace string + setupObjects func() []runtime.Object + wantErr bool + expectedError string + }{ + { + name: "successful capture pods found", + namespace: "default", + setupObjects: func() []runtime.Object { + return []runtime.Object{ + NewLinuxNode("linux-node-1"), + NewWindowsNode("windows-node-1"), + NewDownloadNamespace("default"), + NewCapturePodsWithStatus(testCapture, "default", "linux-node-1", corev1.PodSucceeded), + NewCapturePodsWithStatus(testCapture, "default", "windows-node-1", corev1.PodSucceeded), + } + }, + wantErr: false, + expectedError: "", + }, + { + name: "no capture pods found", + namespace: "default", + setupObjects: func() []runtime.Object { + return []runtime.Object{ + NewLinuxNode("linux-node-1"), + NewDownloadNamespace("default"), + } + }, + wantErr: true, + expectedError: "no pod found for job", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + objects := tc.setupObjects() + kubeClient := newDownloadKubeClient(objects) + + ctx := context.Background() + + // We can't easily test the full downloadFromCluster function due to + // its dependency on creating actual Kubernetes clients, so we'll focus + // on testing the service methods and individual functions + pods, err := getCapturePods(ctx, kubeClient, captureName, tc.namespace) + + if tc.wantErr && err == nil { + t.Errorf("Expected error for test case %s, but got none", tc.name) + } + if tc.wantErr && err != nil && tc.expectedError != "" && !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("Expected error message to contain %q, but got %q", tc.expectedError, err.Error()) + } + if !tc.wantErr && err != nil { + t.Errorf("Unexpected error for test case %s: %v", tc.name, err) + } + if !tc.wantErr && (pods == nil || len(pods.Items) == 0) { + t.Errorf("Expected to find capture pods for %s, but got none", tc.name) + } + + // Validate pod properties + for _, pod := range pods.Items { + if pod.Status.Phase != corev1.PodSucceeded { + t.Errorf("Expected pod phase to be Succeeded, got %s", pod.Status.Phase) + } + + if pod.Labels[label.CaptureNameLabel] != captureName { + t.Errorf("Expected pod to have capture name label %s, got %s", + captureName, pod.Labels[label.CaptureNameLabel]) + } + + // Validate required annotations exist + if _, ok := pod.Annotations[captureConstants.CaptureHostPathAnnotationKey]; !ok { + t.Errorf("Expected pod to have host path annotation") + } + + if _, ok := pod.Annotations[captureConstants.CaptureFilenameAnnotationKey]; !ok { + t.Errorf("Expected pod to have filename annotation") + } + } + + t.Logf("Successfully found %d capture pods for %s", len(pods.Items), tc.name) + }) + } +} + +func TestGetNodeOS(t *testing.T) { + testCases := []struct { + name string + node *corev1.Node + expected NodeOS + wantErr bool + }{ + { + name: "Linux node", + node: NewLinuxNode("linux-test"), + expected: Linux, + wantErr: false, + }, + { + name: "Windows node", + node: NewWindowsNode("windows-test"), + expected: Windows, + wantErr: false, + }, + { + name: "Unknown OS node", + node: &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "unknown-test"}, + Status: corev1.NodeStatus{ + NodeInfo: corev1.NodeSystemInfo{ + OperatingSystem: "darwin", + }, + }, + }, + expected: nil, // nil for unknown OS + wantErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := getNodeOS(tc.node) + + if tc.wantErr && err == nil { + t.Errorf("Expected error for %s, but got none", tc.name) + } + if !tc.wantErr && err != nil { + t.Errorf("Unexpected error for %s: %v", tc.name, err) + } + if result != tc.expected { + t.Errorf("Expected %v, got %v for %s", tc.expected, result, tc.name) + } + }) + } +} + +func TestGetDownloadCmd(t *testing.T) { + testCases := []struct { + name string + node *corev1.Node + hostPath string + fileName string + wantErr bool + validate func(*testing.T, *DownloadCmd, error) + }{ + { + name: "Linux node download cmd", + node: NewLinuxNode("linux-test"), + hostPath: "/tmp/captures", + fileName: testCapture, + wantErr: false, + validate: func(t *testing.T, cmd *DownloadCmd, err error) { + if err != nil { + t.Fatalf("Expected no error, got: %v", err) + } + if cmd == nil { + t.Fatal("Expected DownloadCmd, got nil") + } + if !strings.Contains(cmd.ContainerImage, "busybox") { + t.Errorf("Expected Linux container image to contain 'busybox', got %s", cmd.ContainerImage) + } + if !strings.Contains(cmd.SrcFilePath, "/host/tmp/captures/"+testCapture+".tar.gz") { + t.Errorf("Expected Linux source file path to match pattern, got %s", cmd.SrcFilePath) + } + if cmd.MountPath != "/host/tmp/captures" { + t.Errorf("Expected Linux mount path '/host/tmp/captures', got %s", cmd.MountPath) + } + if len(cmd.KeepAliveCommand) == 0 || cmd.KeepAliveCommand[0] != shellCommand { + t.Errorf("Expected Linux keep alive command to start with 'sh', got %v", cmd.KeepAliveCommand) + } + if len(cmd.FileCheckCommand) == 0 || cmd.FileCheckCommand[0] != shellCommand { + t.Errorf("Expected Linux file check command to start with 'sh', got %v", cmd.FileCheckCommand) + } + if len(cmd.FileReadCommand) == 0 || cmd.FileReadCommand[0] != "cat" { + t.Errorf("Expected Linux file read command to start with 'cat', got %v", cmd.FileReadCommand) + } + }, + }, + { + name: "Windows node download cmd", + node: NewWindowsNode("windows-test"), + hostPath: "/tmp/captures", + fileName: testCapture, + wantErr: false, + validate: func(t *testing.T, cmd *DownloadCmd, err error) { + if err != nil { + t.Fatalf("Expected no error, got: %v", err) + } + if cmd == nil { + t.Fatal("Expected DownloadCmd, got nil") + } + if !strings.Contains(cmd.ContainerImage, "nanoserver") { + t.Errorf("Expected Windows container image to contain 'nanoserver', got %s", cmd.ContainerImage) + } + if !strings.Contains(cmd.SrcFilePath, "C:\\host\\tmp\\captures\\"+testCapture+".tar.gz") { + t.Errorf("Expected Windows source file path to match pattern, got %s", cmd.SrcFilePath) + } + if cmd.MountPath != "C:\\host\\tmp\\captures" { + t.Errorf("Expected Windows mount path 'C:\\host\\tmp\\captures', got %s", cmd.MountPath) + } + if len(cmd.KeepAliveCommand) == 0 || cmd.KeepAliveCommand[0] != cmdCommand { + t.Errorf("Expected Windows keep alive command to start with 'cmd', got %v", cmd.KeepAliveCommand) + } + if len(cmd.FileCheckCommand) == 0 || cmd.FileCheckCommand[0] != cmdCommand { + t.Errorf("Expected Windows file check command to start with 'cmd', got %v", cmd.FileCheckCommand) + } + if len(cmd.FileReadCommand) == 0 || cmd.FileReadCommand[0] != cmdCommand { + t.Errorf("Expected Windows file read command to start with 'cmd', got %v", cmd.FileReadCommand) + } + }, + }, + { + name: "Unsupported node OS", + node: &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "unsupported-test"}, + Status: corev1.NodeStatus{ + NodeInfo: corev1.NodeSystemInfo{ + OperatingSystem: "darwin", + }, + }, + }, + hostPath: "/tmp/captures", + fileName: testCapture, + wantErr: true, + validate: func(t *testing.T, cmd *DownloadCmd, err error) { + if err == nil { + t.Fatal("Expected error for unsupported OS, got nil") + } + if cmd != nil { + t.Errorf("Expected nil DownloadCmd for unsupported OS, got %v", cmd) + } + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := getDownloadCmd(tc.node, tc.hostPath, tc.fileName) + tc.validate(t, result, err) + }) + } +} + +func TestGetWindowsContainerImage(t *testing.T) { + testCases := []struct { + name string + osImage string + expectedSuffix string + }{ + { + name: "Windows Server 2022", + osImage: "Windows Server 2022 Datacenter", + expectedSuffix: "ltsc2022", + }, + { + name: "Windows Server 2019", + osImage: "Windows Server 2019 Datacenter", + expectedSuffix: "ltsc2019", + }, + { + name: "Windows Server 2025", + osImage: "Windows Server 2025 Datacenter", + expectedSuffix: "ltsc2025", + }, + { + name: "Unknown Windows version", + osImage: "Windows Server Unknown", + expectedSuffix: "ltsc2022", // Default + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + node := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "test-node"}, + Status: corev1.NodeStatus{ + NodeInfo: corev1.NodeSystemInfo{ + OSImage: tc.osImage, + }, + }, + } + + result := getWindowsContainerImage(node) + expectedImage := "mcr.microsoft.com/windows/nanoserver:" + tc.expectedSuffix + + if result != expectedImage { + t.Errorf("Expected %s, got %s", expectedImage, result) + } + }) + } +} + +func TestDownloadService(t *testing.T) { + kubeClient := newDownloadKubeClient(nil) + config := &rest.Config{} + namespace := "test-namespace" + + service := NewDownloadService(kubeClient, config, namespace) + + // Test service creation + if service == nil { + t.Fatal("Expected service to be created, got nil") + } + + if service.config != config { + t.Error("Expected config to match") + } + if service.namespace != namespace { + t.Error("Expected namespace to match") + } +} + +func TestGetCapturePods(t *testing.T) { + testCases := []struct { + name string + captureName string + namespace string + setupPods func() []runtime.Object + expectedCount int + wantErr bool + }{ + { + name: "find capture pods successfully", + captureName: testCapture, + namespace: "default", + setupPods: func() []runtime.Object { + return []runtime.Object{ + NewCapturePodsWithStatus(testCapture, "default", "node1", corev1.PodSucceeded), + NewCapturePodsWithStatus(testCapture, "default", "node2", corev1.PodSucceeded), + } + }, + expectedCount: 2, + wantErr: false, + }, + { + name: "no capture pods found", + captureName: "nonexistent-capture", + namespace: "default", + setupPods: func() []runtime.Object { + return []runtime.Object{} + }, + expectedCount: 0, + wantErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + objects := tc.setupPods() + kubeClient := newDownloadKubeClient(objects) + + ctx := context.Background() + pods, err := getCapturePods(ctx, kubeClient, tc.captureName, tc.namespace) + + if tc.wantErr && err == nil { + t.Errorf("Expected error for %s, but got none", tc.name) + } + if !tc.wantErr && err != nil { + t.Errorf("Unexpected error for %s: %v", tc.name, err) + } + if !tc.wantErr && len(pods.Items) != tc.expectedCount { + t.Errorf("Expected %d pods, got %d", tc.expectedCount, len(pods.Items)) + } + }) + } +} + +// Mock test for blob download functionality +func TestDownloadFromBlobValidation(t *testing.T) { + // Test URL parsing validation + testCases := []struct { + name string + blobURL string + wantErr bool + }{ + { + name: "invalid URL", + blobURL: "not-a-valid-url", + wantErr: true, + }, + { + name: "valid https URL but no authentication", + blobURL: "https://storageaccount.blob.core.windows.net/container/blob", + wantErr: true, // Expect error due to missing authentication in test environment + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Set the global variable for the test + originalBlobURL := blobURL + blobURL = tc.blobURL + defer func() { blobURL = originalBlobURL }() + + err := downloadFromBlob() + + if tc.wantErr && err == nil { + t.Errorf("Expected error for %s, but got none", tc.name) + } + if !tc.wantErr && err != nil { + t.Errorf("Unexpected error for %s: %v", tc.name, err) + } + if tc.wantErr && err != nil { + t.Logf("Expected error occurred for %s: %v", tc.name, err) + } + if !tc.wantErr && err == nil { + t.Logf("Successfully completed %s", tc.name) + } + }) + } +} + +func TestDownloadServiceMethods(t *testing.T) { + ctx := context.Background() + + // Setup test objects + objects := []runtime.Object{ + NewLinuxNode("test-node"), + NewDownloadNamespace("test-namespace"), + } + + kubeClient := newDownloadKubeClient(objects) + config := &rest.Config{} + service := NewDownloadService(kubeClient, config, "test-namespace") + + t.Run("createDownloadPod creates pod correctly", func(t *testing.T) { + downloadCmd := &DownloadCmd{ + ContainerImage: "mcr.microsoft.com/azurelinux/busybox:1.36", + MountPath: "/host/tmp/captures", + KeepAliveCommand: []string{"sh", "-c", "echo 'Download pod ready'; sleep 3600"}, + } + + pod, err := service.createDownloadPod(ctx, "test-node", "/tmp/captures", testCapture, downloadCmd) + if err != nil { + t.Fatalf("Expected no error, got: %v", err) + } + + if pod == nil { + t.Fatal("Expected pod to be created, got nil") + } + + if pod.Spec.NodeName != "test-node" { + t.Errorf("Expected NodeName to be 'test-node', got: %s", pod.Spec.NodeName) + } + + if len(pod.Spec.Containers) != 1 { + t.Errorf("Expected 1 container, got: %d", len(pod.Spec.Containers)) + } + + container := pod.Spec.Containers[0] + if container.Image != downloadCmd.ContainerImage { + t.Errorf("Expected container image %s, got: %s", downloadCmd.ContainerImage, container.Image) + } + }) + + t.Run("waitForPodReady handles pod states correctly", func(t *testing.T) { + // This test is limited due to the fake client behavior + // In a real scenario, we would test timeout and different pod phases + podName := "test-pod-ready" + + // Create a pod that should be running + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: service.namespace, + }, + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + }, + } + + // Add pod to client + _, err := service.kubeClient.CoreV1().Pods(service.namespace).Create(ctx, pod, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Failed to create test pod: %v", err) + } + + readyPod, err := service.waitForPodReady(ctx, podName) + if err != nil { + t.Fatalf("Expected no error waiting for pod, got: %v", err) + } + + if readyPod.Status.Phase != corev1.PodRunning { + t.Errorf("Expected pod phase Running, got: %s", readyPod.Status.Phase) + } + }) +} + +func TestDownloadServiceErrorHandling(t *testing.T) { + ctx := context.Background() + kubeClient := newDownloadKubeClient(nil) + config := &rest.Config{} + service := NewDownloadService(kubeClient, config, "test-namespace") + + t.Run("DownloadFile handles unsupported node OS", func(t *testing.T) { + // Create a node with unsupported OS + unsupportedNode := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "unsupported-node"}, + Status: corev1.NodeStatus{ + NodeInfo: corev1.NodeSystemInfo{ + OperatingSystem: "darwin", // Unsupported OS + }, + }, + } + + // Add the node to the client + _, err := service.kubeClient.CoreV1().Nodes().Create(ctx, unsupportedNode, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Failed to create test node: %v", err) + } + + err = service.DownloadFile(ctx, "unsupported-node", "/tmp", testFile, testCapture) + if err == nil { + t.Error("Expected error for unsupported node OS, got nil") + } + + if !errors.Is(err, ErrUnsupportedNodeOS) { + t.Errorf("Expected ErrUnsupportedNodeOS, got: %v", err) + } + }) + + t.Run("DownloadFile handles missing node", func(t *testing.T) { + err := service.DownloadFile(ctx, "nonexistent-node", "/tmp", testFile, testCapture) + if err == nil { + t.Error("Expected error for missing node, got nil") + } + + if !strings.Contains(err.Error(), "failed to get node information") { + t.Errorf("Expected error about missing node, got: %v", err) + } + }) +} + +func TestDownloadCommandFlags(t *testing.T) { + testCases := []struct { + name string + args []string + validate func(*testing.T, *cobra.Command) + }{ + { + name: "valid name flag provided", + args: []string{"--name", testCapture}, + validate: func(t *testing.T, cmd *cobra.Command) { + nameFlag := cmd.Flag("name") + if nameFlag == nil { + t.Error("Expected name flag to exist") + return + } + + if nameFlag.Value.String() != testCapture { + t.Errorf("Expected name flag value '%s', got '%s'", testCapture, nameFlag.Value.String()) + } + }, + }, + { + name: "valid blob-url flag provided", + args: []string{"--blob-url", "https://storageaccount.blob.core.windows.net/container/blob?sastoken"}, + validate: func(t *testing.T, cmd *cobra.Command) { + blobURLFlag := cmd.Flag("blob-url") + if blobURLFlag == nil { + t.Error("Expected blob-url flag to exist") + return + } + + expectedURL := "https://storageaccount.blob.core.windows.net/container/blob?sastoken" + if blobURLFlag.Value.String() != expectedURL { + t.Errorf("Expected blob-url flag value '%s', got '%s'", expectedURL, blobURLFlag.Value.String()) + } + }, + }, + { + name: "name with custom output path", + args: []string{"--name", testCapture, "--output", "/tmp/downloads"}, + validate: func(t *testing.T, cmd *cobra.Command) { + nameFlag := cmd.Flag("name") + outputFlag := cmd.Flag("output") + + if nameFlag == nil { + t.Error("Expected name flag to exist") + return + } + if outputFlag == nil { + t.Error("Expected output flag to exist") + return + } + + if nameFlag.Value.String() != testCapture { + t.Errorf("Expected name flag value '%s', got '%s'", testCapture, nameFlag.Value.String()) + } + + if outputFlag.Value.String() != "/tmp/downloads" { + t.Errorf("Expected output flag value '/tmp/downloads', got '%s'", outputFlag.Value.String()) + } + }, + }, + { + name: "both name and blob-url flags", + args: []string{"--name", testCapture, "--blob-url", "https://example.com/blob"}, + validate: func(t *testing.T, cmd *cobra.Command) { + nameFlag := cmd.Flag("name") + blobURLFlag := cmd.Flag("blob-url") + + if nameFlag == nil { + t.Error("Expected name flag to exist") + return + } + if blobURLFlag == nil { + t.Error("Expected blob-url flag to exist") + return + } + + if nameFlag.Value.String() != testCapture { + t.Errorf("Expected name flag value '%s', got '%s'", testCapture, nameFlag.Value.String()) + } + + if blobURLFlag.Value.String() != "https://example.com/blob" { + t.Errorf("Expected blob-url flag value 'https://example.com/blob', got '%s'", blobURLFlag.Value.String()) + } + }, + }, + { + name: "missing required flags", + args: []string{}, + validate: func(t *testing.T, cmd *cobra.Command) { + // Test the validation logic directly by checking global variables + // Save original values + originalCaptureName := captureName + originalBlobURL := blobURL + captureName = "" + blobURL = "" + defer func() { + captureName = originalCaptureName + blobURL = originalBlobURL + }() + + // Test the validation condition directly + if captureName == "" && blobURL == "" { + t.Log("Correctly identified missing required flags") + } else { + t.Error("Should have identified missing required flags") + } + + // Verify the command has the expected flags defined + nameFlag := cmd.Flag("name") + blobURLFlag := cmd.Flag("blob-url") + outputFlag := cmd.Flag("output") + + if nameFlag == nil { + t.Error("Expected name flag to be defined") + } + if blobURLFlag == nil { + t.Error("Expected blob-url flag to be defined") + } + if outputFlag == nil { + t.Error("Expected output flag to be defined") + } + + // Test that both flags have empty default values + if nameFlag != nil && nameFlag.DefValue != "" { + t.Errorf("Expected name flag default to be empty, got '%s'", nameFlag.DefValue) + } + if blobURLFlag != nil && blobURLFlag.DefValue != "" { + t.Errorf("Expected blob-url flag default to be empty, got '%s'", blobURLFlag.DefValue) + } + }, + }, + } + + // Test all cases with unified approach + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cmd := NewDownloadSubCommand() + + // Parse flags without executing the command + err := cmd.ParseFlags(tc.args) + if err != nil { + t.Fatalf("Failed to parse flags: %v", err) + } + + tc.validate(t, cmd) + }) + } +} diff --git a/pkg/capture/constants/job_specification.go b/pkg/capture/constants/job_specification.go index 5e484d0916..569455facd 100644 --- a/pkg/capture/constants/job_specification.go +++ b/pkg/capture/constants/job_specification.go @@ -20,8 +20,10 @@ const ( CaptureContainerEntrypoint string = "./retina/captureworkload" CaptureContainerEntrypointWin string = "captureworkload.exe" - CaptureAppname string = "capture" - CaptureContainername string = "capture" + CaptureAppname string = "capture" + CaptureContainername string = "capture" + DownloadAppname string = "download" + DownloadContainerName string = "download" // CaptureOutputLocationBlobUploadSecretName is the name of the secret that stores the blob upload url. CaptureOutputLocationBlobUploadSecretName string = "capture-blob-upload-secret" diff --git a/pkg/capture/utils/label.go b/pkg/capture/utils/label.go index 4882f1cf24..c83d5aee52 100644 --- a/pkg/capture/utils/label.go +++ b/pkg/capture/utils/label.go @@ -28,3 +28,10 @@ func GetContainerLabelsFromCaptureName(captureName string) map[string]string { label.CaptureNameLabel: captureName, } } + +func GetDownloadLabelsFromCaptureName(captureName string) map[string]string { + return map[string]string{ + label.AppLabel: captureConstants.DownloadAppname, + label.CaptureNameLabel: captureName, + } +} From 18da0e98e1c48e49bd00ed0b7b3b6876b828fca5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 22:32:23 -0400 Subject: [PATCH 151/448] deps: bump sigstore/cosign-installer from 3.10.0 to 4.0.0 (#1914) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.10.0 to 4.0.0.
Release notes

Sourced from sigstore/cosign-installer's releases.

v4.0.0

What's Changed?

Note: You must upgrade to cosign-installer v4 if you want to install Cosign v3+. You may still install Cosign v2.x with cosign-installer v4.

In version v3+, using cosign sign-blob requires adding the --bundle flag which may require you to update your signing command.

  • Add support for Cosign v3 releases (#201)

v3.10.1

What's Changed?

Note: cosign-installer v3.x cannot be used to install Cosign v3.x. You must upgrade to cosign-installer v4 in order to use Cosign v3.

Note: This is planned to be the final release of Cosign v2, though we will cut new releases for any critical security or bug fixes. We recommend transitioning to Cosign v3.

  • Bump default Cosign to v2.6.1 (#203)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=3.10.0&new-version=4.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 6f44f214cd..aa2e2c856d 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -27,7 +27,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 9fe92ac3b2..bed68e3234 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -32,7 +32,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -78,7 +78,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -124,7 +124,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -169,7 +169,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -212,7 +212,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -260,7 +260,7 @@ jobs: uses: docker/setup-qemu-action@v3 - name: Install Cosign - uses: sigstore/cosign-installer@v3.10.0 + uses: sigstore/cosign-installer@v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From fb788f0fd87e29754ec741b143aba091ca2b7f22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 10:56:50 -0400 Subject: [PATCH 152/448] deps: bump actions/upload-artifact from 4.6.2 to 5.0.0 (#1918) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 5.0.0.
Release notes

Sourced from actions/upload-artifact's releases.

v5.0.0

What's Changed

BREAKING CHANGE: this update supports Node v24.x. This is not a breaking change per-se but we're treating it as such.

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v4...v5.0.0

Commits
  • 330a01c Merge pull request #734 from actions/danwkennedy/prepare-5.0.0
  • 03f2824 Update github.dep.yml
  • 905a1ec Prepare v5.0.0
  • 2d9f9cd Merge pull request #725 from patrikpolyak/patch-1
  • 9687587 Merge branch 'main' into patch-1
  • 2848b2c Merge pull request #727 from danwkennedy/patch-1
  • 9b51177 Spell out the first use of GHES
  • cd231ca Update GHES guidance to include reference to Node 20 version
  • de65e23 Merge pull request #712 from actions/nebuk89-patch-1
  • 8747d8c Update README.md
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=4.6.2&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index a6e88312eb..2884d91643 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -36,7 +36,7 @@ jobs: make test-image IMAGE_NAMESPACE=${{ github.repository }} PLATFORM=linux/amd64 - name: Upload Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: coverage-files path: ./artifacts/coverage* From 34e8f5f72fb2550f305dc52b22a9d2d587877b7f Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Tue, 28 Oct 2025 15:28:14 +0000 Subject: [PATCH 153/448] deps: Updating hubble to mitigate cve from v1.17.5 to v1.18.3 (#1920) This pull request makes a minor update to the `Makefile`, specifically updating the default `HUBBLE_VERSION` to a newer release. * Updated the default value of `HUBBLE_VERSION` from `v1.17.5` to `v1.18.3` in the `Makefile` to use the latest version.# Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image image image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dd6ae3cce1..81d1d95097 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ PLATFORM ?= $(OS)/$(ARCH) PLATFORMS ?= linux/amd64 linux/arm64 windows/amd64 OS_VERSION ?= ltsc2019 -HUBBLE_VERSION ?= v1.17.5 +HUBBLE_VERSION ?= v1.18.3 CONTAINER_BUILDER ?= docker CONTAINER_RUNTIME ?= docker From cbfce9b40ec1e18719594813a30855a7b0a75dff Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:02:21 +0000 Subject: [PATCH 154/448] fix(dropreason): Check ftrace_enabled required for fexit programs (#1926) # Description Adds a check for `/proc/sys/kernel/ftrace_enabled` before deciding to use fexit eBPF programs. When ftrace is disabled, the plugin will fall back to kprobes. ## Changes - Added `IsFtraceEnabled()` helper function in `pkg/plugin/common/common_linux.go` that reads `/proc/sys/kernel/ftrace_enabled` - Updated `getEbpfPayload()` to check ftrace status and log it - Modified `resolvePayload()` to accept `ftraceEnabled` parameter and only use fexit programs when ftrace is enabled (in addition to existing kernel version/architecture requirements) - Updated documentation to clarify that fexit programs require ftrace to be enabled ## Behavior - **Before**: Plugin would attempt to use fexit programs based only on kernel version and architecture, potentially failing when ftrace is disabled - **After**: Plugin checks ftrace status and gracefully falls back to kprobes when ftrace is disabled ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Verified on kernel 6.6.0 with both ftrace enabled and disabled scenarios. When ftrace is enabled fexit programs are used. When ftrace is disabled, the plugin uses kprobes/kretprobes. image image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/plugin/common/common_linux.go | 10 +++++++ .../dropreason/dropreason_linux_test.go | 29 ++++++++++++++++++- pkg/plugin/dropreason/ebpfsetup_linux.go | 24 ++++++++++----- test/plugin/dropreason/main_linux.go | 2 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/pkg/plugin/common/common_linux.go b/pkg/plugin/common/common_linux.go index 16f7695722..b666066028 100644 --- a/pkg/plugin/common/common_linux.go +++ b/pkg/plugin/common/common_linux.go @@ -138,3 +138,13 @@ func readIDField(path string) string { } return "" } + +// IsFtraceEnabled checks if ftrace is enabled in the kernel. +// This is required for fexit/fentry programs to work. +func IsFtraceEnabled() bool { + data, err := os.ReadFile("/proc/sys/kernel/ftrace_enabled") + if err != nil { + return false + } + return strings.TrimSpace(string(data)) == "1" +} diff --git a/pkg/plugin/dropreason/dropreason_linux_test.go b/pkg/plugin/dropreason/dropreason_linux_test.go index 675b81f20f..6e59e1d2af 100644 --- a/pkg/plugin/dropreason/dropreason_linux_test.go +++ b/pkg/plugin/dropreason/dropreason_linux_test.go @@ -484,6 +484,7 @@ func TestResolveEbpfPayload(t *testing.T) { kv semver.Version isMariner bool isPodLevel bool + ftraceEnabled bool wantType string wantSupportsFexit bool }{ @@ -493,6 +494,7 @@ func TestResolveEbpfPayload(t *testing.T) { kv: mustVersion("5.4.0"), isMariner: false, isPodLevel: false, + ftraceEnabled: true, wantType: "*dropreason.allKprobeObjects", wantSupportsFexit: false, }, @@ -502,6 +504,7 @@ func TestResolveEbpfPayload(t *testing.T) { kv: mustVersion("5.10.0"), isMariner: false, isPodLevel: false, + ftraceEnabled: true, wantType: "*dropreason.allFexitObjects", wantSupportsFexit: true, }, @@ -511,6 +514,7 @@ func TestResolveEbpfPayload(t *testing.T) { kv: mustVersion("5.10.0"), isMariner: true, isPodLevel: false, + ftraceEnabled: true, wantType: "*dropreason.marinerObjects", wantSupportsFexit: true, }, @@ -520,6 +524,7 @@ func TestResolveEbpfPayload(t *testing.T) { kv: mustVersion("5.8.0"), isMariner: true, isPodLevel: false, + ftraceEnabled: true, wantType: "*dropreason.allKprobeObjects", wantSupportsFexit: false, }, @@ -529,6 +534,7 @@ func TestResolveEbpfPayload(t *testing.T) { kv: mustVersion("6.1.0"), isMariner: true, isPodLevel: false, + ftraceEnabled: true, wantType: "*dropreason.marinerObjects", wantSupportsFexit: true, }, @@ -538,6 +544,27 @@ func TestResolveEbpfPayload(t *testing.T) { kv: mustVersion("5.15.0"), isMariner: false, isPodLevel: true, + ftraceEnabled: true, + wantType: "*dropreason.allKprobeObjects", + wantSupportsFexit: false, + }, + { + name: "mariner with ftrace disabled - fallback to kprobes", + arch: "amd64", + kv: mustVersion("5.15.0"), + isMariner: true, + isPodLevel: false, + ftraceEnabled: false, + wantType: "*dropreason.allKprobeObjects", + wantSupportsFexit: false, + }, + { + name: "ubuntu with ftrace disabled - fallback to kprobes", + arch: "amd64", + kv: mustVersion("6.6.0"), + isMariner: false, + isPodLevel: false, + ftraceEnabled: false, wantType: "*dropreason.allKprobeObjects", wantSupportsFexit: false, }, @@ -545,7 +572,7 @@ func TestResolveEbpfPayload(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - objs, _, isFexit := resolvePayload(tt.arch, tt.kv, tt.isMariner, tt.isPodLevel) + objs, _, isFexit := resolvePayload(tt.arch, tt.kv, tt.isMariner, tt.isPodLevel, tt.ftraceEnabled) if isFexit != tt.wantSupportsFexit { t.Errorf("isFexit = %v, want %v", isFexit, tt.wantSupportsFexit) diff --git a/pkg/plugin/dropreason/ebpfsetup_linux.go b/pkg/plugin/dropreason/ebpfsetup_linux.go index c0c0a6785d..c67efabe0a 100644 --- a/pkg/plugin/dropreason/ebpfsetup_linux.go +++ b/pkg/plugin/dropreason/ebpfsetup_linux.go @@ -28,6 +28,7 @@ eBPF Program Support Matrix Program Type Selection: - If: + - Ftrace is enabled AND - Arch == amd64 and kernel >= 5.5 - Arch == arm64 and kernel >= 6.0 → Use `fexit` @@ -44,13 +45,15 @@ Scope Selection: +-----------+------------------------+--------------+--------+ | Distro | Arch + Kernel | Prog | Scope | +-----------+------------------------+--------------+--------+ -| Mariner | amd64, kernel >= 5.5 | fexit | core | -| Mariner | arm64, kernel >= 6.0 | fexit | core | -| Non-Marin | amd64, kernel >= 5.5 | fexit | all | -| Non-Marin | arm64, kernel >= 6.0 | fexit | all | +| Mariner | amd64, kernel >= 5.5 | fexit* | core | +| Mariner | arm64, kernel >= 6.0 | fexit* | core | +| Non-Marin | amd64, kernel >= 5.5 | fexit* | all | +| Non-Marin | arm64, kernel >= 6.0 | fexit* | all | | * | (otherwise) | kprobe | per OS | +-----------+------------------------+--------------+--------+ +* fexit requires ftrace to be enabled in the kernel + core kernel funcs: - tcp_v4_connect - inet_csk_accept @@ -74,16 +77,21 @@ func (dr *dropReason) getEbpfPayload() (objs interface{}, maps *kprobeMaps, supp } dr.l.Info("Detected kernel", zap.String("version", kv.String())) - objs, maps, supportsFexit = resolvePayload(runtime.GOARCH, kv, isMariner, dr.cfg.EnablePodLevel) + // Check if ftrace is enabled (required for fexit programs) + ftraceEnabled := plugincommon.IsFtraceEnabled() + dr.l.Info("Ftrace status", zap.Bool("enabled", ftraceEnabled)) + + objs, maps, supportsFexit = resolvePayload(runtime.GOARCH, kv, isMariner, dr.cfg.EnablePodLevel, ftraceEnabled) return objs, maps, supportsFexit, nil } -func resolvePayload(arch string, kv semver.Version, isMariner, isPodLevel bool) (interface{}, *kprobeMaps, bool) { +func resolvePayload(arch string, kv semver.Version, isMariner, isPodLevel, ftraceEnabled bool) (interface{}, *kprobeMaps, bool) { minVersionAmd64, _ := versioncheck.Version(MinAmdVersionNum) minVersionArm64, _ := versioncheck.Version(MinArmVersionNum) - supportsFexit := (arch == "amd64" && kv.GTE(minVersionAmd64)) || - (arch == "arm64" && kv.GTE(minVersionArm64)) + supportsFexit := ftraceEnabled && + ((arch == "amd64" && kv.GTE(minVersionAmd64)) || + (arch == "arm64" && kv.GTE(minVersionArm64))) var objs interface{} var maps *kprobeMaps diff --git a/test/plugin/dropreason/main_linux.go b/test/plugin/dropreason/main_linux.go index 06fb3754c7..e38fa4c9a3 100644 --- a/test/plugin/dropreason/main_linux.go +++ b/test/plugin/dropreason/main_linux.go @@ -30,7 +30,7 @@ func main() { cfg := &kcfg.Config{ MetricsInterval: 1 * time.Second, - EnablePodLevel: true, + EnablePodLevel: true, // Set to false to test fexit programs } // Filtermanager. From e68a3ecd2dd587c754ea7d64c6123f399425b958 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:26:30 -0500 Subject: [PATCH 155/448] deps: bump helm/kind-action from 1.12.0 to 1.13.0 (#1925) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.12.0 to 1.13.0.
Release notes

Sourced from helm/kind-action's releases.

v1.13.0

What's Changed

New Contributors

Full Changelog: https://github.com/helm/kind-action/compare/v1...v1.13.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=helm/kind-action&package-manager=github_actions&previous-version=1.12.0&new-version=1.13.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-validation.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index 9aa41d5d4b..2f2db33547 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -40,7 +40,7 @@ jobs: helm pull oci://ghcr.io/microsoft/retina/charts/retina --version ${{ env.TAG }} - name: Setup kind cluster - uses: helm/kind-action@v1.12.0 + uses: helm/kind-action@v1.13.0 # krew does not support installing a specific verison # so if this step fails it means there was something wrong From a58597a120051a91f673729c0e149ba0942ca939 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 19:55:49 -0500 Subject: [PATCH 156/448] deps: bump golangci/golangci-lint-action from 8 to 9 (#1930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 8 to 9.
Release notes

Sourced from golangci/golangci-lint-action's releases.

v9.0.0

In the scope of this release, we change Nodejs runtime from node20 to node24 (https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/).

What's Changed

Changes

Full Changelog: https://github.com/golangci/golangci-lint-action/compare/v8.0.0...v9.0.0

Commits
  • 0a35821 docs: update readme
  • 043b1b8 feat: support Module Plugin System (#1306)
  • a66d26a feat: add install-only option (#1305)
  • 7fe1b22 build(deps): bump the dependencies group with 2 updates (#1303)
  • 14973f1 build(deps-dev): bump the dev-dependencies group with 2 updates (#1299)
  • 8c2d575 build(deps): bump @​types/node from 24.8.1 to 24.9.1 in the dependencies group...
  • b002b6e build(deps): bump actions/setup-node from 5 to 6 (#1296)
  • c13f4ed build(deps): bump @​types/node from 24.7.2 to 24.8.1 in the dependencies group...
  • b68d21b docs: improve readme
  • 06188a2 build(deps): bump github/codeql-action from 3 to 4 (#1293)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golangci/golangci-lint-action&package-manager=github_actions&previous-version=8&new-version=9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/golangci-lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index c5aeca76bd..399db01207 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -30,7 +30,7 @@ jobs: go-version-file: go.mod - name: golangci-lint if: env.IS_NOT_MERGE_GROUP - uses: golangci/golangci-lint-action@v8 + uses: golangci/golangci-lint-action@v9 with: version: latest args: --concurrency 4 --verbose --config=.golangci.yaml --timeout=25m From 86174a3d336403c82f479f6a048778eabca2b276 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:31:05 +0000 Subject: [PATCH 157/448] fix: Clean up before building windows image for git checks (#1950) # Description Windows build is timing out with the error below. The GA runner is running out of memory. Cleaning up before building the windows image makes enough space for the image to be build successfully. This logic was already introduced for the ` dev/v0.0.33-windows` branch here https://github.com/microsoft/retina/pull/1935/files `Build Agent Windows Images (windows, amd64, 2019) System.IO.IOException: No space left on device : '/home/runner/actions-runner/cached/_diag/Worker_20251124-112903-utc.log' at System.IO.RandomAccess.WriteAtOffset(SafeFileHandle handle, ReadOnlySpan1 buffer, Int64 fileOffset) at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder) at System.Diagnostics.TextWriterTraceListener.Flush() at GitHub.Runner.Common.HostTraceListener.WriteHeader(String source, TraceEventType eventType, Int32 id) at System.Diagnostics.TraceSource.TraceEvent(TraceEventType eventType, Int32 id, String message) at GitHub.Runner.Worker.Worker.RunAsync(String pipeIn, String pipeOut) at GitHub.Runner.Worker.Program.MainAsync(IHostContext context, String[] args) System.IO.IOException: No space left on device : '/home/runner/actions-runner/cached/_diag/Worker_20251124-112903-utc.log' at System.IO.RandomAccess.WriteAtOffset(SafeFileHandle handle, ReadOnlySpan1 buffer, Int64 fileOffset) at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder) at System.Diagnostics.TextWriterTraceListener.Flush() at GitHub.Runner.Common.HostTraceListener.WriteHeader(String source, TraceEventType eventType, Int32 id) at System.Diagnostics.TraceSource.TraceEvent(TraceEventType eventType, Int32 id, String message) at GitHub.Runner.Common.Tracing.Error(Exception exception) at GitHub.Runner.Worker.Program.MainAsync(IHostContext context, String[] args) Unhandled exception. System.IO.IOException: No space left on device : '/home/runner/actions-runner/cached/_diag/Worker_20251124-112903-utc.log' at System.IO.RandomAccess.WriteAtOffset(SafeFileHandle handle, ReadOnlySpan 1 buffer, Int64 fileOffset) at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder) at System.Diagnostics.TextWriterTraceListener.Flush() at System.Diagnostics.TraceSource.Flush() at GitHub.Runner.Common.Tracing.Dispose(Boolean disposing) at GitHub.Runner.Common.Tracing.Dispose() at GitHub.Runner.Common.TraceManager.Dispose(Boolean disposing) at GitHub.Runner.Common.TraceManager.Dispose() at GitHub.Runner.Common.HostContext.Dispose(Boolean disposing) at GitHub.Runner.Common.HostContext.Dispose() at GitHub.Runner.Worker.Program.Main(String[] args)` ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed The github action workflow is succeeding Also build the windows ltsc2019 agent image and used it to create a capture. No issues found image ## Additional Notes This seems to be caused by an update to the base image for the ltsc2019 build Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/workflows/images.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index f046f7ee47..5005eb374b 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -91,6 +91,14 @@ jobs: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION }} + + - run: df -h + - name: "node-cleanup" + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL + sudo docker image prune --all --force + sudo docker builder prune -a + - run: df -h - name: Build Images shell: bash From 1e177e613ddc4f98208f90c01de9c27b600ed386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:44:13 +0000 Subject: [PATCH 158/448] deps: bump actions/setup-go from 6.0.0 to 6.1.0 (#1944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.0.0 to 6.1.0.
Release notes

Sourced from actions/setup-go's releases.

v6.1.0

What's Changed

Enhancements

Dependency updates

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.1.0

Commits
  • 4dc6199 Bump semver and @​types/semver (#652)
  • f3787be Add comprehensive breaking changes documentation for v6 (#674)
  • 3a0c2c8 Bump actions/publish-action from 0.3.0 to 0.4.0 (#641)
  • faf5242 Add support for .tool-versions file in setup-go, update workflow (#673)
  • 7bc60db Fall back to downloading from go.dev/dl instead of storage.googleapis.com/gol...
  • c0137ca Bump eslint-config-prettier from 10.0.1 to 10.1.8 and document breaking chang...
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=6.0.0&new-version=6.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 12 ++++++------ .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-images.yaml | 10 +++++----- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 686846cb93..fbd3eddd98 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go if: env.IS_NOT_MERGE_GROUP - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - name: Initialize CodeQL diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 57f7e8d33e..f14e364346 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -89,7 +89,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 399db01207..8e1db636e0 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,7 +24,7 @@ jobs: if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 if: env.IS_NOT_MERGE_GROUP with: go-version-file: go.mod diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 32b87c19e1..c9b7a2a3e9 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -18,7 +18,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - name: Run GoReleaser build @@ -39,7 +39,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - name: Run GoReleaser release diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 5005eb374b..eb0fdc8ac5 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -25,7 +25,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -76,7 +76,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -136,7 +136,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -186,7 +186,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -235,7 +235,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -321,7 +321,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index 9526be45c6..aac4320f24 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -51,7 +51,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index bed68e3234..7eedf6cf87 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -26,7 +26,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -72,7 +72,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -118,7 +118,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -163,7 +163,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version @@ -206,7 +206,7 @@ jobs: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 8405dea778..6fc2eeca23 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -71,7 +71,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index ef868d6271..1d8fa283f3 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2884d91643..94e8374b15 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version-file: go.mod From 1da328c5982cb332eaec92de4d51f41fb278a78c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:44:32 +0000 Subject: [PATCH 159/448] deps: bump actions/checkout from 5.0.0 to 6.0.0 (#1945) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.0.0.
Release notes

Sourced from actions/checkout's releases.

v6.0.0

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v5.0.0...v6.0.0

v6-beta

What's Changed

Updated persist-credentials to store the credentials under $RUNNER_TEMP instead of directly in the local git config.

This requires a minimum Actions Runner version of v2.329.0 to access the persisted credentials for Docker container action scenarios.

v5.0.1

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v5...v5.0.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=5.0.0&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/docs.yaml | 2 +- .github/workflows/e2e-test-event-writer.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 14 +++++++------- .github/workflows/kapinger.yaml | 2 +- .github/workflows/markdownlint.yaml | 2 +- .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ .github/workflows/release-validation.yaml | 2 +- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- .github/workflows/trivy.yaml | 2 +- .github/workflows/update-hubble.yaml | 2 +- 18 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index fbd3eddd98..ca2cdd35d5 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository if: env.IS_NOT_MERGE_GROUP - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup go if: env.IS_NOT_MERGE_GROUP uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 5bf0f8d9e4..4e0ff298ff 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-node@v6 with: node-version: 20 diff --git a/.github/workflows/e2e-test-event-writer.yml b/.github/workflows/e2e-test-event-writer.yml index 216d3f86a9..d0cea32c4e 100644 --- a/.github/workflows/e2e-test-event-writer.yml +++ b/.github/workflows/e2e-test-event-writer.yml @@ -31,4 +31,4 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index f14e364346..c84b391a6e 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -86,7 +86,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 8e1db636e0..2919882677 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -20,7 +20,7 @@ jobs: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index c9b7a2a3e9..07eeee0593 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: fetch-depth: 0 - name: Set up Go @@ -35,7 +35,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: fetch-depth: 0 - name: Set up Go diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index eb0fdc8ac5..1c43df4a91 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -74,7 +74,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -134,7 +134,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -184,7 +184,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -233,7 +233,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -290,7 +290,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup QEMU uses: docker/setup-qemu-action@v3 @@ -318,7 +318,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 227ce6b77e..25d39044e9 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Set outputs id: vars diff --git a/.github/workflows/markdownlint.yaml b/.github/workflows/markdownlint.yaml index db68bd3eaa..f216de3bf7 100644 --- a/.github/workflows/markdownlint.yaml +++ b/.github/workflows/markdownlint.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: DavidAnson/markdownlint-cli2-action@v9 with: command: config diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index aac4320f24..3834d1ca57 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index aa2e2c856d..fd6affb823 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -19,7 +19,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 7eedf6cf87..109a5bc4dd 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -116,7 +116,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -161,7 +161,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -204,7 +204,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -254,7 +254,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index 2f2db33547..535a450843 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 - name: Get latest tag id: get_latest_tag diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 6fc2eeca23..b03702d912 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -68,7 +68,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 1d8fa283f3..29db32b7b4 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -15,7 +15,7 @@ jobs: tofu_version: 1.8.3 - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Set up Go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 94e8374b15..91aefaf46b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index a82a292260..43688982e4 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest # trivy only supports running on Linux steps: - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Get Tag run: | diff --git a/.github/workflows/update-hubble.yaml b/.github/workflows/update-hubble.yaml index 006b662471..96fbbadb79 100644 --- a/.github/workflows/update-hubble.yaml +++ b/.github/workflows/update-hubble.yaml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Get latest Hubble version id: get_version From 9768dab0e1689b075aca05a1cde6bbf0fe62e0ab Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 1 Dec 2025 16:06:58 -0500 Subject: [PATCH 160/448] fix(conntrack): fix compilation warning + fix subsequent stack size error (#1927) This patch fixes the operator precedence compilation warning when evaluating whether a packet is a SYN-ACK. This fix then introduced a stack size too large error, in which this patch also fixed by passing ct_keys by pointers instead of value to the helper functions. # Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- pkg/plugin/conntrack/_cprog/conntrack.c | 35 ++++++++++++------- .../packetparser/mocks/mock_types_linux.go | 4 --- pkg/plugin/packetparser/types_linux.go | 2 +- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c index 38fc62305c..be648d8198 100644 --- a/pkg/plugin/conntrack/_cprog/conntrack.c +++ b/pkg/plugin/conntrack/_cprog/conntrack.c @@ -234,7 +234,7 @@ static __always_inline __u8 _ct_get_traffic_direction(__u8 observation_point) { * @arg observation_point The point in the network stack where the packet is observed. * @arg is_reply true if the packet is a SYN-ACK packet. False if it is a SYN packet. */ -static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key key, __u8 observation_point, bool is_reply) { +static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key *key, __u8 observation_point, bool is_reply) { struct ct_entry new_value; __builtin_memset(&new_value, 0, sizeof(struct ct_entry)); __u64 now = bpf_mono_now(); @@ -272,7 +272,7 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru // Update packet p->is_reply = is_reply; p->traffic_direction = new_value.traffic_direction; - bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY); + bpf_map_update_elem(&retina_conntrack, key, &new_value, BPF_ANY); return true; } @@ -282,7 +282,10 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru * @arg key The key to be used to create the new connection. * @arg observation_point The point in the network stack where the packet is observed. */ -static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct ct_v4_key key, __u8 observation_point) { +static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct ct_v4_key *key, __u8 observation_point) { + if (!p || !key) { + return false; + } struct ct_entry new_value; __builtin_memset(&new_value, 0, sizeof(struct ct_entry)); __u64 now = bpf_mono_now(); @@ -306,7 +309,7 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c // Update packet p->is_reply = false; p->traffic_direction = new_value.traffic_direction; - bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY); + bpf_map_update_elem(&retina_conntrack, key, &new_value, BPF_ANY); return true; } @@ -317,12 +320,15 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c * @arg reverse_key The reverse key to be used to handle the connection. * @arg observation_point The point in the network stack where the packet is observed. */ -static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct ct_v4_key key, struct ct_v4_key reverse_key, __u8 observation_point) { +static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct ct_v4_key *key, struct ct_v4_key *reverse_key, __u8 observation_point) { + if (!p || !key || !reverse_key) { + return false; + } u8 tcp_handshake = p->flags & (TCP_SYN|TCP_ACK); if (tcp_handshake == TCP_SYN) { // We have a SYN, we set `is_reply` to false and we provide `key` return _ct_create_new_tcp_connection(p, key, observation_point, false); - } else if(tcp_handshake == TCP_SYN|TCP_ACK) { + } else if(tcp_handshake == (TCP_SYN|TCP_ACK)) { // We have a SYN-ACK, we set `is_reply` to true and we provide `reverse_key` return _ct_create_new_tcp_connection(p, reverse_key, observation_point, true); } @@ -354,7 +360,7 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c new_value.conntrack_metadata.bytes_rx_count = p->bytes; new_value.conntrack_metadata.packets_rx_count = 1; #endif // ENABLE_CONNTRACK_METRICS - bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY); + bpf_map_update_elem(&retina_conntrack, reverse_key, &new_value, BPF_ANY); } else { // Otherwise, the packet is considered as a packet in the send direction. p->is_reply = false; new_value.flags_seen_tx_dir = p->flags; @@ -365,7 +371,7 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c new_value.conntrack_metadata.bytes_tx_count = p->bytes; new_value.conntrack_metadata.packets_tx_count = 1; #endif // ENABLE_CONNTRACK_METRICS - bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY); + bpf_map_update_elem(&retina_conntrack, key, &new_value, BPF_ANY); } #ifdef ENABLE_CONNTRACK_METRICS // Update packet's conntrack metadata. @@ -381,12 +387,15 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c * @arg reverse_key The reverse key to be used to handle the connection. * @arg observation_point The point in the network stack where the packet is observed. */ -static __always_inline struct packetreport _ct_handle_new_connection(struct packet *p, struct ct_v4_key key, struct ct_v4_key reverse_key, __u8 observation_point) { +static __always_inline struct packetreport _ct_handle_new_connection(struct packet *p, struct ct_v4_key *key, struct ct_v4_key *reverse_key, __u8 observation_point) { struct packetreport report; __builtin_memset(&report, 0, sizeof(struct packetreport)); - if (key.proto & IPPROTO_TCP) { + if (!p || !key || !reverse_key) { + return report; + } + if (key->proto & IPPROTO_TCP) { report.report = _ct_handle_tcp_connection(p, key, reverse_key, observation_point); - } else if (key.proto & IPPROTO_UDP) { + } else if (key->proto & IPPROTO_UDP) { report.report = _ct_handle_udp_connection(p, key, observation_point); } else { report.report = false; // We are not interested in other protocols. @@ -618,5 +627,5 @@ static __always_inline __attribute__((unused)) struct packetreport ct_process_pa } // If the connection is still not found, the connection is new. - return _ct_handle_new_connection(p, key, reverse_key, observation_point); -} \ No newline at end of file + return _ct_handle_new_connection(p, &key, &reverse_key, observation_point); +} diff --git a/pkg/plugin/packetparser/mocks/mock_types_linux.go b/pkg/plugin/packetparser/mocks/mock_types_linux.go index 5b6ce7599b..0019773e74 100644 --- a/pkg/plugin/packetparser/mocks/mock_types_linux.go +++ b/pkg/plugin/packetparser/mocks/mock_types_linux.go @@ -22,7 +22,6 @@ import ( type Mockqdisc struct { ctrl *gomock.Controller recorder *MockqdiscMockRecorder - isgomock struct{} } // MockqdiscMockRecorder is the mock recorder for Mockqdisc. @@ -74,7 +73,6 @@ func (mr *MockqdiscMockRecorder) Delete(info any) *gomock.Call { type Mockfilter struct { ctrl *gomock.Controller recorder *MockfilterMockRecorder - isgomock struct{} } // MockfilterMockRecorder is the mock recorder for Mockfilter. @@ -112,7 +110,6 @@ func (mr *MockfilterMockRecorder) Add(info any) *gomock.Call { type Mocknltc struct { ctrl *gomock.Controller recorder *MocknltcMockRecorder - isgomock struct{} } // MocknltcMockRecorder is the mock recorder for Mocknltc. @@ -192,7 +189,6 @@ func (mr *MocknltcMockRecorder) SetOption(arg0, arg1 any) *gomock.Call { type MockperfReader struct { ctrl *gomock.Controller recorder *MockperfReaderMockRecorder - isgomock struct{} } // MockperfReaderMockRecorder is the mock recorder for MockperfReader. diff --git a/pkg/plugin/packetparser/types_linux.go b/pkg/plugin/packetparser/types_linux.go index c220ba65af..7f1e1abe25 100644 --- a/pkg/plugin/packetparser/types_linux.go +++ b/pkg/plugin/packetparser/types_linux.go @@ -80,7 +80,7 @@ type tcValue struct { qdisc *tc.Object } -//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types.go -package=mocks +//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types_linux.go -package=mocks // tc qdisc interface type qdisc interface { From bd82e82f74180488173e7642fcc39f895f5e8328 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:07:16 -0500 Subject: [PATCH 161/448] chore(deps): bump js-yaml from 3.14.1 to 3.14.2 in /site in the npm_and_yarn group across 1 directory (#1933) Bumps the npm_and_yarn group with 1 update in the /site directory: [js-yaml](https://github.com/nodeca/js-yaml). Updates `js-yaml` from 3.14.1 to 3.14.2
Changelog

Sourced from js-yaml's changelog.

[3.14.2] - 2025-11-15

Security

  • Backported v4.1.1 fix to v3

[4.1.1] - 2025-11-12

Security

  • Fix prototype pollution issue in yaml merge (<<) operator.

[4.1.0] - 2021-04-15

Added

  • Types are now exported as yaml.types.XXX.
  • Every type now has options property with original arguments kept as they were (see yaml.types.int.options as an example).

Changed

  • Schema.extend() now keeps old type order in case of conflicts (e.g. Schema.extend([ a, b, c ]).extend([ b, a, d ]) is now ordered as abcd instead of cbad).

[4.0.0] - 2021-01-03

Changed

  • Check migration guide to see details for all breaking changes.
  • Breaking: "unsafe" tags !!js/function, !!js/regexp, !!js/undefined are moved to js-yaml-js-types package.
  • Breaking: removed safe* functions. Use load, loadAll, dump instead which are all now safe by default.
  • yaml.DEFAULT_SAFE_SCHEMA and yaml.DEFAULT_FULL_SCHEMA are removed, use yaml.DEFAULT_SCHEMA instead.
  • yaml.Schema.create(schema, tags) is removed, use schema.extend(tags) instead.
  • !!binary now always mapped to Uint8Array on load.
  • Reduced nesting of /lib folder.
  • Parse numbers according to YAML 1.2 instead of YAML 1.1 (01234 is now decimal, 0o1234 is octal, 1:23 is parsed as string instead of base60).
  • dump() no longer quotes :, [, ], (, ) except when necessary, #470, #557.
  • Line and column in exceptions are now formatted as (X:Y) instead of at line X, column Y (also present in compact format), #332.
  • Code snippet created in exceptions now contains multiple lines with line numbers.
  • dump() now serializes undefined as null in collections and removes keys with undefined in mappings, #571.
  • dump() with skipInvalid=true now serializes invalid items in collections as null.
  • Custom tags starting with ! are now dumped as !tag instead of !<!tag>, #576.
  • Custom tags starting with tag:yaml.org,2002: are now shorthanded using !!, #258.

Added

  • Added .mjs (es modules) support.
  • Added quotingType and forceQuotes options for dumper to configure string literal style, #290, #529.
  • Added styles: { '!!null': 'empty' } option for dumper (serializes { foo: null } as "foo: "), #570.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=js-yaml&package-manager=npm_and_yarn&previous-version=3.14.1&new-version=3.14.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 45 +++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index b67ddd76bc..fb5fb2d401 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -239,6 +239,7 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.0.tgz", "integrity": "sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-common": "5.40.0", "@algolia/requester-browser-xhr": "5.40.0", @@ -364,6 +365,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2155,6 +2157,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2177,6 +2180,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2286,6 +2290,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2707,6 +2712,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3658,6 +3664,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/core": "3.9.1", "@docusaurus/logger": "3.9.1", @@ -4768,6 +4775,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.0.tgz", "integrity": "sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5082,6 +5090,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5455,6 +5464,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.7.tgz", "integrity": "sha512-KUnDCJF5+AiZd8owLIeVHqmW9yM4sqmDVf2JRJiBMFkGvkoZ4/WyV2lL4zVsoinmRS/W3FeEdZLEWFRofnT2FQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5791,6 +5801,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5863,6 +5874,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5908,6 +5920,7 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.0.tgz", "integrity": "sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/abtesting": "1.6.0", "@algolia/client-abtesting": "5.40.0", @@ -6489,6 +6502,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -7507,6 +7521,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9039,6 +9054,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -9539,9 +9555,9 @@ } }, "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -10856,9 +10872,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -13750,6 +13766,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14265,6 +14282,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15138,6 +15156,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15967,6 +15986,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -15978,6 +15998,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -16030,6 +16051,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -16056,6 +16078,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17200,6 +17223,7 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, + "peer": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -17943,6 +17967,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18203,7 +18228,8 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "peer": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18274,6 +18300,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "devOptional": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18636,6 +18663,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18839,6 +18867,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -19108,6 +19137,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -19495,6 +19525,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From fa6299033723012b63c1653935185a6f9974715f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:34:32 +0000 Subject: [PATCH 162/448] deps: bump github.com/redis/go-redis/v9 from 9.7.1 to 9.7.3 (#1954) Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.7.1 to 9.7.3.
Release notes

Sourced from github.com/redis/go-redis/v9's releases.

v9.7.3

What's Changed

  • fix: handle network error on SETINFO (#3295) (CVE-2025-29923)
  • Deprecating misspelled DisableIndentity flag in the client options.
  • Introducing DisableIdentity flag in the client options.
  • Updating the documentation related to the new flag and the one that was deprecated.

Full Changelog: https://github.com/redis/go-redis/compare/v9.7.1...v9.7.3

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/redis/go-redis/v9&package-manager=go_modules&previous-version=9.7.1&new-version=9.7.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9b5eb80053..39fad2816b 100644 --- a/go.mod +++ b/go.mod @@ -575,7 +575,7 @@ require ( github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/raeperd/recvcheck v0.2.0 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 // indirect - github.com/redis/go-redis/v9 v9.7.1 // indirect + github.com/redis/go-redis/v9 v9.7.3 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/ryancurrah/gomodguard v1.3.5 // indirect diff --git a/go.sum b/go.sum index 24ad6e4b04..f1691f9e1e 100644 --- a/go.sum +++ b/go.sum @@ -1283,8 +1283,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1 h1:+o7rrBoj54t8fqQSmnwRLdLzp5 github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1/go.mod h1:bWIjbxmrAk9eKGg9LSko3oQefoYGyWV4xzNS55PgL60= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 h1:LJF39lvUagUpKfL2/gZIp5vHv3AwXt9zOZ/Xual/CzI= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1/go.mod h1:VAY1vDpD/dLwfw/wU5SsexXNhCO9DjhRoGkmJeFONoE= -github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc= -github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= +github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= From 5022b85bc429234e2867c9a80284c72d4fa42e22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:34:48 +0000 Subject: [PATCH 163/448] chore(deps): bump the npm_and_yarn group across 1 directory with 2 updates (#1955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 2 updates in the /site directory: [express](https://github.com/expressjs/express) and [node-forge](https://github.com/digitalbazaar/forge). Updates `express` from 4.21.2 to 4.22.1
Release notes

Sourced from express's releases.

v4.22.1

What's Changed

Full Changelog: https://github.com/expressjs/express/compare/4.22.0...v4.22.1

4.22.0

Important: Security

What's Changed

Full Changelog: https://github.com/expressjs/express/compare/4.21.2...4.22.0

Changelog

Sourced from express's changelog.

4.22.1 / 2025-12-01

4.22.0 / 2025-12-01

Commits

Updates `node-forge` from 1.3.1 to 1.3.2
Changelog

Sourced from node-forge's changelog.

1.3.2 - 2025-11-25

Security

  • HIGH: ASN.1 Validator Desynchronization
    • An Interpretation Conflict (CWE-436) vulnerability in node-forge versions 1.3.1 and below enables remote, unauthenticated attackers to craft ASN.1 structures to desynchronize schema validations, yielding a semantic divergence that may bypass downstream cryptographic verifications and security decisions.
    • Reported by Hunter Wodzenski.
    • CVE ID: CVE-2025-12816
    • GHSA ID: GHSA-5gfm-wpxj-wjgq
  • HIGH: ASN.1 Unbounded Recursion
    • An Uncontrolled Recursion (CWE-674) vulnerability in node-forge versions 1.3.1 and below enables remote, unauthenticated attackers to craft deep ASN.1 structures that trigger unbounded recursive parsing. This leads to a Denial-of-Service (DoS) via stack exhaustion when parsing untrusted DER inputs.
    • Reported by Hunter Wodzenski.
    • CVE ID: CVE-2025-66031
    • GHSA ID: GHSA-554w-wpv2-vw27
  • MODERATE: ASN.1 OID Integer Truncation
    • An Integer Overflow (CWE-190) vulnerability in node-forge versions 1.3.1 and below enables remote, unauthenticated attackers to craft ASN.1 structures containing OIDs with oversized arcs. These arcs may be decoded as smaller, trusted OIDs due to 32-bit bitwise truncation, enabling the bypass of downstream OID-based security decisions.
    • Reported by Hunter Wodzenski.
    • CVE ID: CVE-2025-66030
    • GHSA ID: GHSA-65ch-62r8-g69g

Fixed

  • [asn1] Fix for vulnerability identified by CVE-2025-12816 PKCS#12 MAC verification bypass due to missing macData enforcement and improper asn1.validate routine.
  • [asn1] Add fromDer() max recursion depth check.
    • Add a asn1.maxDepth global configurable maximum depth of 256.
    • Add a asn1.fromDer() per-call maxDepth option.
    • NOTE: The default maximum is assumed to be higher than needed for valid data. If this assumption is false then this could be a breaking change. Please file an issue if there are use cases that need a higher maximum.
    • NOTE: The per-call maxDepth parameter has not been exposed up through all of the API stack due to the complexities involved. Please file an issue if there are use cases that require this instead of changing the default maximum.
  • [asn1] Improve OID handling.
    • Error on parsed OID values larger than 2**32 - 1.
    • Error on DER OID values larger than 2**53 - 1 .
Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 53 +++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index fb5fb2d401..e54e8af740 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -8807,39 +8807,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -8885,6 +8885,21 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/express/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -13661,9 +13676,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" From 63b4cb7d10b22ecfbd92de2e5bf3a9a519114699 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Tue, 2 Dec 2025 13:44:02 +0000 Subject: [PATCH 164/448] fix: add validation of error to k8sWatcherErrorHandler (#1952) # Description add validation of error to k8sWatcherErrorHandler ## Related Issue #1951 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- pkg/k8s/watcher_linux.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/k8s/watcher_linux.go b/pkg/k8s/watcher_linux.go index e1a119b03c..be1081a5b8 100644 --- a/pkg/k8s/watcher_linux.go +++ b/pkg/k8s/watcher_linux.go @@ -43,7 +43,12 @@ func Start(ctx context.Context, k *watchers.K8sWatcher) { // retinaK8sErrorHandler is a custom error handler for the watcher // that logs the error and tags the error to easily identify func k8sWatcherErrorHandler(c context.Context, e error, s string, i ...interface{}) { + if e == nil { + return + } + errStr := e.Error() + logError := func(er, r string) { logger.WithFields(logrus.Fields{ "underlyingError": er, From 41cb718f57c3e89d409ad575e4a5dfadb7fec25e Mon Sep 17 00:00:00 2001 From: Artem <122204149+letv1nnn@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:24:32 +0000 Subject: [PATCH 165/448] fix: removed unused option PrevTCPSockStats from linux util (#1924) # Description I removed unused code from linux_util, specifically PrevTCPSockStats. I also added some entries to gitignore including test-summary(generated after make test) and ignoring logs. ## Related Issue This pr related to #1066 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed I've provided two screenshots, one from make test, another is just linting. testing image Linting image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Co-authored-by: Alex Castilio --- .gitignore | 5 +++++ pkg/plugin/linuxutil/linuxutil_linux.go | 10 ++++------ pkg/plugin/linuxutil/types_linux.go | 3 --- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 0fbcc3c9c5..1171f198e4 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out +# logs +*.log + # Dependency directories (remove the comment below to include it) # vendor/ @@ -48,3 +51,5 @@ netperf-*.csv .certs/ artifacts/ + +test-summary \ No newline at end of file diff --git a/pkg/plugin/linuxutil/linuxutil_linux.go b/pkg/plugin/linuxutil/linuxutil_linux.go index a6647ae8dd..c1b460eabe 100644 --- a/pkg/plugin/linuxutil/linuxutil_linux.go +++ b/pkg/plugin/linuxutil/linuxutil_linux.go @@ -82,10 +82,9 @@ func (lu *linuxUtil) run(ctx context.Context) error { return nil case <-ticker.C: opts := &NetstatOpts{ - CuratedKeys: true, - AddZeroVal: false, - ListenSock: false, - PrevTCPSockStats: lu.prevTCPSockStats, + CuratedKeys: true, + AddZeroVal: false, + ListenSock: false, } var wg sync.WaitGroup @@ -94,11 +93,10 @@ func (lu *linuxUtil) run(ctx context.Context) error { wg.Add(1) go func() { defer wg.Done() - tcpSocketStats, err := nsReader.readAndUpdate() + _, err := nsReader.readAndUpdate() if err != nil { lu.l.Error("Reading netstat failed", zap.Error(err)) } - lu.prevTCPSockStats = tcpSocketStats }() ethtoolOpts := &EthtoolOpts{ diff --git a/pkg/plugin/linuxutil/types_linux.go b/pkg/plugin/linuxutil/types_linux.go index 35f94d7328..83d1e0a956 100644 --- a/pkg/plugin/linuxutil/types_linux.go +++ b/pkg/plugin/linuxutil/types_linux.go @@ -88,9 +88,6 @@ type NetstatOpts struct { // get only listening sockets ListenSock bool - - // previous TCP socket stats - PrevTCPSockStats *SocketStats } type EthtoolStats struct { From a33f34bd8dcb3bef1fb10021045e1dc0835e4faa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 10:30:00 -0500 Subject: [PATCH 166/448] chore(deps): bump mdast-util-to-hast from 13.2.0 to 13.2.1 in /site in the npm_and_yarn group across 1 directory (#1956) Bumps the npm_and_yarn group with 1 update in the /site directory: [mdast-util-to-hast](https://github.com/syntax-tree/mdast-util-to-hast). Updates `mdast-util-to-hast` from 13.2.0 to 13.2.1
Release notes

Sourced from mdast-util-to-hast's releases.

13.2.1

Fix

  • ab3a795 Fix support for spaces in class names

Types

  • efb5312 Refactor to use @imports
  • a5bc210 Add declaration maps

Full Changelog: https://github.com/syntax-tree/mdast-util-to-hast/compare/13.2.0...13.2.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mdast-util-to-hast&package-manager=npm_and_yarn&previous-version=13.2.0&new-version=13.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index e54e8af740..eab30316e1 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -11542,9 +11542,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", From 963901b6ff32410df9efbb208d217b77c5badf3f Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:43:27 +0000 Subject: [PATCH 167/448] feat: Add download all and all namespaces flags (#1917) # Description Allow user to download all captures from a specific namespace or from all namespaces ## Related Issue https://github.com/microsoft/retina/issues/1836 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/cmd/capture/download.go | 281 ++++++++++++++++++++++++++++--- cli/cmd/capture/download_test.go | 204 +++++++++++++++++++++- docs/04-Captures/02-cli.md | 91 +++++++++- 3 files changed, 549 insertions(+), 27 deletions(-) diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index 6443857270..9729ad4764 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -4,7 +4,9 @@ package capture import ( + "archive/tar" "bytes" + "compress/gzip" "context" "errors" "fmt" @@ -20,11 +22,13 @@ import ( "github.com/Azure/azure-sdk-for-go/storage" retinacmd "github.com/microsoft/retina/cli/cmd" captureConstants "github.com/microsoft/retina/pkg/capture/constants" + captureFile "github.com/microsoft/retina/pkg/capture/file" captureUtils "github.com/microsoft/retina/pkg/capture/utils" captureLabels "github.com/microsoft/retina/pkg/label" "github.com/spf13/cobra" "github.com/spf13/viper" "go.uber.org/zap" + batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" @@ -69,6 +73,8 @@ var ( ErrNoBlobsFound = errors.New("no blobs found with prefix") captureName string outputPath string + downloadAll bool + downloadAllNamespaces bool ) var ( @@ -79,6 +85,8 @@ var ( ErrEmptyDownloadOutput = errors.New("download command produced no output") ErrFailedToCreateDownloadPod = errors.New("failed to create download pod") ErrUnsupportedNodeOS = errors.New("unsupported node operating system") + ErrMissingRequiredFlags = errors.New("either --name, --blob-url, or --all must be specified") + ErrAllNamespacesRequiresAll = errors.New("--all-namespaces flag can only be used with --all flag") ) // DownloadCmd holds all OS-specific commands and configurations @@ -98,6 +106,12 @@ type DownloadService struct { namespace string } +// Key represents a unique capture identifier +type Key struct { + Name string + Namespace string +} + // NewDownloadService creates a new download service with shared dependencies func NewDownloadService(kubeClient kubernetes.Interface, config *rest.Config, namespace string) *DownloadService { return &DownloadService{ @@ -198,6 +212,12 @@ var downloadExample = templates.Examples(i18n.T(` # Download the capture file(s) created using the capture name and define output location kubectl retina capture download --name -o + # Download all available captures + kubectl retina capture download --all + + # Download all available captures from all namespaces + kubectl retina capture download --all --all-namespaces + # Download capture file(s) from Blob Storage via Blob URL (Blob URL requires Read/List permissions) kubectl retina capture download --blob-url "" `)) @@ -248,49 +268,61 @@ func downloadFromCluster(ctx context.Context, config *rest.Config, namespace str // DownloadFile downloads a capture file from a specific node func (ds *DownloadService) DownloadFile(ctx context.Context, nodeName, hostPath, fileName, captureName string) error { + content, err := ds.DownloadFileContent(ctx, nodeName, hostPath, fileName, captureName) + if err != nil { + return err + } + + outputFile := filepath.Join(outputPath, captureName, fileName+".tar.gz") + fmt.Printf("Bytes retrieved: %d\n", len(content)) + + err = os.WriteFile(outputFile, content, 0o600) + if err != nil { + return errors.Join(ErrWriteFileToHost, err) + } + + fmt.Printf("File written to: %s\n", outputFile) + return nil +} + +// DownloadFileContent downloads a capture file from a specific node and returns the content +func (ds *DownloadService) DownloadFileContent(ctx context.Context, nodeName, hostPath, fileName, captureName string) ([]byte, error) { node, err := ds.kubeClient.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{}) if err != nil { - return errors.Join(ErrGetNodeInfo, err) + return nil, errors.Join(ErrGetNodeInfo, err) } downloadCmd, err := getDownloadCmd(node, hostPath, fileName) if err != nil { - return err + return nil, err } fmt.Println("File to be downloaded: ", downloadCmd.SrcFilePath) downloadPod, err := ds.createDownloadPod(ctx, nodeName, hostPath, captureName, downloadCmd) if err != nil { - return err + return nil, err } + // Ensure cleanup + defer func() { + cleanupErr := ds.kubeClient.CoreV1().Pods(ds.namespace).Delete(ctx, downloadPod.Name, metav1.DeleteOptions{}) + if cleanupErr != nil { + retinacmd.Logger.Warn("Failed to clean up debug pod", zap.String("name", downloadPod.Name), zap.Error(cleanupErr)) + } + }() + fileExists, err := ds.verifyFileExists(ctx, downloadPod, downloadCmd) if err != nil || !fileExists { - return err + return nil, err } fmt.Println("Obtaining file...") fileContent, err := ds.executeFileDownload(ctx, downloadPod, downloadCmd) if err != nil { - return err - } - - outputFile := filepath.Join(outputPath, captureName, fileName+".tar.gz") - fmt.Printf("Bytes retrieved: %d\n", len(fileContent)) - - err = os.WriteFile(outputFile, fileContent, 0o600) - if err != nil { - return errors.Join(ErrWriteFileToHost, err) + return nil, err } - fmt.Printf("File written to: %s\n", outputFile) - - // Ensure cleanup - err = ds.kubeClient.CoreV1().Pods(ds.namespace).Delete(ctx, downloadPod.Name, metav1.DeleteOptions{}) - if err != nil { - retinacmd.Logger.Warn("Failed to clean up debug pod", zap.String("name", downloadPod.Name), zap.Error(err)) - } - return nil + return fileContent, nil } func getCapturePods(ctx context.Context, kubeClient kubernetes.Interface, captureName, namespace string) (*corev1.PodList, error) { @@ -513,6 +545,195 @@ func downloadFromBlob() error { return nil } +func downloadAllCaptures(ctx context.Context, config *rest.Config, namespace string) error { + if downloadAllNamespaces { + fmt.Println("Downloading all captures from all namespaces...") + } else { + fmt.Printf("Downloading all captures for namespace %s...\n", namespace) + } + kubeClient, err := kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf("failed to initialize k8s client: %w", err) + } + + // List all capture jobs with the capture app label + captureJobSelector := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + captureLabels.AppLabel: captureConstants.CaptureAppname, + }, + } + labelSelector, err := metav1.LabelSelectorAsSelector(captureJobSelector) + if err != nil { + return fmt.Errorf("failed to parse label selector: %w", err) + } + + var jobList *batchv1.JobList + if downloadAllNamespaces { + // Search across all namespaces + jobList, err = kubeClient.BatchV1().Jobs("").List(ctx, metav1.ListOptions{ + LabelSelector: labelSelector.String(), + }) + if err != nil { + return fmt.Errorf("failed to list capture jobs across all namespaces: %w", err) + } + } else { + // Search in specified namespace only + jobList, err = kubeClient.BatchV1().Jobs(namespace).List(ctx, metav1.ListOptions{ + LabelSelector: labelSelector.String(), + }) + if err != nil { + return fmt.Errorf("failed to list capture jobs: %w", err) + } + } + + if len(jobList.Items) == 0 { + if downloadAllNamespaces { + fmt.Printf("No captures found across all namespaces\n") + } else { + fmt.Printf("No captures found in namespace %s\n", namespace) + } + return nil + } + + // Group jobs by capture name and namespace + captureToJobs := make(map[Key][]batchv1.Job) + for i := range jobList.Items { + job := &jobList.Items[i] + captureNameFromLabel, ok := job.Labels[captureLabels.CaptureNameLabel] + if !ok { + continue + } + key := Key{Name: captureNameFromLabel, Namespace: job.Namespace} + captureToJobs[key] = append(captureToJobs[key], *job) + } + + fmt.Printf("Found %d capture(s) to download\n", len(captureToJobs)) + + // Create the final archive using streaming approach to avoid memory issues + timestamp := captureFile.TimeToString(captureFile.Now()) + finalArchivePath := filepath.Join(outputPath, fmt.Sprintf("all-captures-%s.tar.gz", timestamp)) + + fmt.Printf("Creating final archive: %s\n", finalArchivePath) + err = createStreamingTarGzArchive(ctx, finalArchivePath, captureToJobs, kubeClient, config) + if err != nil { + return fmt.Errorf("failed to create final archive: %w", err) + } + + fmt.Printf("Successfully created archive: %s\n", finalArchivePath) + return nil +} + +// createStreamingTarGzArchive creates a tar.gz archive by streaming files one at a time to avoid memory issues +func createStreamingTarGzArchive(ctx context.Context, outputPath string, captureToJobs map[Key][]batchv1.Job, kubeClient kubernetes.Interface, config *rest.Config) error { + // Create the output file + outFile, err := os.Create(outputPath) + if err != nil { + return fmt.Errorf("failed to create archive file: %w", err) + } + defer outFile.Close() + + // Create gzip writer + gzipWriter := gzip.NewWriter(outFile) + defer gzipWriter.Close() + + // Create tar writer + tarWriter := tar.NewWriter(gzipWriter) + defer tarWriter.Close() + + // We'll create download services per namespace as needed + downloadServices := make(map[string]*DownloadService) + fileCount := 0 + + // Process each capture and stream files directly to archive + for captureKey := range captureToJobs { + currentCaptureName := captureKey.Name + currentNamespace := captureKey.Namespace + fmt.Printf("Processing capture: %s in namespace: %s\n", currentCaptureName, currentNamespace) + + // Get or create download service for this namespace + downloadService, exists := downloadServices[currentNamespace] + if !exists { + downloadService = NewDownloadService(kubeClient, config, currentNamespace) + downloadServices[currentNamespace] = downloadService + } + + // Get pods for this capture and download files + pods, podsErr := getCapturePods(ctx, kubeClient, currentCaptureName, currentNamespace) + if podsErr != nil { + fmt.Printf("Warning: Failed to get pods for capture %s in namespace %s: %v\n", currentCaptureName, currentNamespace, podsErr) + continue + } + + for i := range pods.Items { + pod := pods.Items[i] + if pod.Status.Phase != corev1.PodSucceeded { + fmt.Printf("Warning: Pod %s is not in Succeeded phase (status: %s), skipping\n", pod.Name, pod.Status.Phase) + continue + } + + nodeName := pod.Spec.NodeName + hostPath, ok := pod.Annotations[captureConstants.CaptureHostPathAnnotationKey] + if !ok { + fmt.Printf("Warning: Cannot obtain host path from pod annotations for %s\n", pod.Name) + continue + } + fileName, ok := pod.Annotations[captureConstants.CaptureFilenameAnnotationKey] + if !ok { + fmt.Printf("Warning: Cannot obtain capture file name from pod annotations for %s\n", pod.Name) + continue + } + + // Download file content (this is still done in memory per file, but not all files at once) + content, err := downloadService.DownloadFileContent(ctx, nodeName, hostPath, fileName, currentCaptureName) + if err != nil { + fmt.Printf("Warning: Failed to download file from pod %s: %v\n", pod.Name, err) + continue + } + + // Determine archive path based on whether we're using all namespaces + var archivePath string + if downloadAllNamespaces { + // Include namespace in path: namespace/captureName/fileName.tar.gz + archivePath = filepath.Join(currentNamespace, currentCaptureName, fileName+".tar.gz") + } else { + // Original path: captureName/fileName.tar.gz + archivePath = filepath.Join(currentCaptureName, fileName+".tar.gz") + } + + // Stream file directly to archive + header := &tar.Header{ + Name: archivePath, + Mode: 0o600, + Size: int64(len(content)), + } + + // Write header + if err := tarWriter.WriteHeader(header); err != nil { + return fmt.Errorf("failed to write header for %s: %w", archivePath, err) + } + + // Write content + if _, err := tarWriter.Write(content); err != nil { + return fmt.Errorf("failed to write content for %s: %w", archivePath, err) + } + + fileCount++ + fmt.Printf("Added %s (%d bytes) to archive\n", archivePath, len(content)) + } + } + + if fileCount == 0 { + // Remove the empty archive file + outFile.Close() + os.Remove(outputPath) + fmt.Println("No capture files were successfully downloaded") + return nil + } + + fmt.Printf("Successfully added %d files to archive\n", fileCount) + return nil +} + func NewDownloadSubCommand() *cobra.Command { downloadCapture := &cobra.Command{ Use: "download", @@ -534,8 +755,13 @@ func NewDownloadSubCommand() *cobra.Command { captureNamespace = "default" } - if captureName == "" && blobURL == "" { - return errors.New("either --name or --blob-url must be specified") + if captureName == "" && blobURL == "" && !downloadAll { + return ErrMissingRequiredFlags + } + + // Validate all-namespaces flag usage + if downloadAllNamespaces && !downloadAll { + return ErrAllNamespacesRequiresAll } if captureName != "" { @@ -552,12 +778,21 @@ func NewDownloadSubCommand() *cobra.Command { } } + if downloadAll { + err = downloadAllCaptures(ctx, kubeConfig, captureNamespace) + if err != nil { + return err + } + } + return nil }, } downloadCapture.Flags().StringVar(&blobURL, "blob-url", "", "Blob URL from which to download") downloadCapture.Flags().StringVar(&captureName, "name", "", "The name of a the capture") + downloadCapture.Flags().BoolVar(&downloadAll, "all", false, "Download all available captures for the specified namespace (or all namespaces if --all-namespaces flag is set)") + downloadCapture.Flags().BoolVar(&downloadAllNamespaces, "all-namespaces", false, "Download captures from all namespaces (only works with --all flag)") downloadCapture.Flags().StringVarP(&outputPath, "output", "o", DefaultOutputPath, "Path to save the downloaded capture") return downloadCapture diff --git a/cli/cmd/capture/download_test.go b/cli/cmd/capture/download_test.go index dbc2180789..4769d4b348 100644 --- a/cli/cmd/capture/download_test.go +++ b/cli/cmd/capture/download_test.go @@ -764,15 +764,18 @@ func TestDownloadCommandFlags(t *testing.T) { // Save original values originalCaptureName := captureName originalBlobURL := blobURL + originalDownloadAll := downloadAll captureName = "" blobURL = "" + downloadAll = false defer func() { captureName = originalCaptureName blobURL = originalBlobURL + downloadAll = originalDownloadAll }() // Test the validation condition directly - if captureName == "" && blobURL == "" { + if captureName == "" && blobURL == "" && !downloadAll { t.Log("Correctly identified missing required flags") } else { t.Error("Should have identified missing required flags") @@ -781,6 +784,7 @@ func TestDownloadCommandFlags(t *testing.T) { // Verify the command has the expected flags defined nameFlag := cmd.Flag("name") blobURLFlag := cmd.Flag("blob-url") + allFlag := cmd.Flag("all") outputFlag := cmd.Flag("output") if nameFlag == nil { @@ -789,17 +793,111 @@ func TestDownloadCommandFlags(t *testing.T) { if blobURLFlag == nil { t.Error("Expected blob-url flag to be defined") } + if allFlag == nil { + t.Error("Expected all flag to be defined") + } if outputFlag == nil { t.Error("Expected output flag to be defined") } - // Test that both flags have empty default values + // Test that flags have expected default values if nameFlag != nil && nameFlag.DefValue != "" { t.Errorf("Expected name flag default to be empty, got '%s'", nameFlag.DefValue) } if blobURLFlag != nil && blobURLFlag.DefValue != "" { t.Errorf("Expected blob-url flag default to be empty, got '%s'", blobURLFlag.DefValue) } + if allFlag != nil && allFlag.DefValue != "false" { + t.Errorf("Expected all flag default to be false, got '%s'", allFlag.DefValue) + } + }, + }, + { + name: "valid all flag provided", + args: []string{"--all"}, + validate: func(t *testing.T, cmd *cobra.Command) { + allFlag := cmd.Flag("all") + if allFlag == nil { + t.Error("Expected all flag to be defined") + return + } + + if allFlag.Value.String() != "true" { + t.Errorf("Expected all flag value 'true', got '%s'", allFlag.Value.String()) + } + }, + }, + { + name: "all flag with custom output path", + args: []string{"--all", "-o", "/custom/path"}, + validate: func(t *testing.T, cmd *cobra.Command) { + allFlag := cmd.Flag("all") + outputFlag := cmd.Flag("output") + + if allFlag == nil { + t.Error("Expected all flag to be defined") + return + } + if outputFlag == nil { + t.Error("Expected output flag to be defined") + return + } + + if allFlag.Value.String() != "true" { + t.Errorf("Expected all flag value 'true', got '%s'", allFlag.Value.String()) + } + + if outputFlag.Value.String() != "/custom/path" { + t.Errorf("Expected output flag value '/custom/path', got '%s'", outputFlag.Value.String()) + } + }, + }, + { + name: "all-namespaces flag with all flag", + args: []string{"--all", "--all-namespaces"}, + validate: func(t *testing.T, _ *cobra.Command) { + if !downloadAll { + t.Error("Expected downloadAll to be true") + } + if !downloadAllNamespaces { + t.Error("Expected downloadAllNamespaces to be true") + } + if captureName != "" { + t.Error("Expected captureName to be empty") + } + if blobURL != "" { + t.Error("Expected blobURL to be empty") + } + }, + }, + { + name: "all-namespaces flag without all flag (should fail validation)", + args: []string{"--all-namespaces"}, + validate: func(t *testing.T, _ *cobra.Command) { + if downloadAll { + t.Error("Expected downloadAll to be false") + } + if !downloadAllNamespaces { + t.Error("Expected downloadAllNamespaces to be true") + } + // This should fail validation in the actual command execution + // but we can't test that here since we're only parsing flags + }, + }, + { + name: "all-namespaces with name flag (should fail validation)", + args: []string{"--name", "test", "--all-namespaces"}, + validate: func(t *testing.T, _ *cobra.Command) { + if downloadAll { + t.Error("Expected downloadAll to be false") + } + if !downloadAllNamespaces { + t.Error("Expected downloadAllNamespaces to be true") + } + if captureName != "test" { + t.Error("Expected captureName to be 'test'") + } + // This should fail validation in the actual command execution }, }, } @@ -819,3 +917,105 @@ func TestDownloadCommandFlags(t *testing.T) { }) } } + +func TestDownloadAllCapturesGracefulErrorHandling(t *testing.T) { + // Test the graceful error handling by testing individual components + // that are used in downloadAllCaptures + + testCases := []struct { + name string + pod *corev1.Pod + expectSkip bool + description string + }{ + { + name: "successful pod", + pod: NewCapturePodsWithStatus("test-capture", "default", "node1", corev1.PodSucceeded), + expectSkip: false, + description: "Pod with Succeeded status should be processed", + }, + { + name: "failed pod", + pod: NewCapturePodsWithStatus("test-capture", "default", "node1", corev1.PodFailed), + expectSkip: true, + description: "Pod with Failed status should be skipped with warning", + }, + { + name: "running pod", + pod: NewCapturePodsWithStatus("test-capture", "default", "node1", corev1.PodRunning), + expectSkip: true, + description: "Pod with Running status should be skipped with warning", + }, + { + name: "pod missing host path annotation", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "default", + Labels: map[string]string{ + label.CaptureNameLabel: "test-capture", + }, + Annotations: map[string]string{ + // Missing CaptureHostPathAnnotationKey + captureConstants.CaptureFilenameAnnotationKey: "test-file", + }, + }, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{Phase: corev1.PodSucceeded}, + }, + expectSkip: true, + description: "Pod missing host path annotation should be skipped with warning", + }, + { + name: "pod missing filename annotation", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "default", + Labels: map[string]string{ + label.CaptureNameLabel: "test-capture", + }, + Annotations: map[string]string{ + captureConstants.CaptureHostPathAnnotationKey: "/tmp/captures", + // Missing CaptureFilenameAnnotationKey + }, + }, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{Phase: corev1.PodSucceeded}, + }, + expectSkip: true, + description: "Pod missing filename annotation should be skipped with warning", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Test the logic that would be used in downloadAllCaptures + shouldSkip := false + + // Check pod status + if tc.pod.Status.Phase != corev1.PodSucceeded { + shouldSkip = true + t.Logf("Pod %s would be skipped due to status: %s", tc.pod.Name, tc.pod.Status.Phase) + } + + // Check annotations if pod status is good + if !shouldSkip { + if _, ok := tc.pod.Annotations[captureConstants.CaptureHostPathAnnotationKey]; !ok { + shouldSkip = true + t.Logf("Pod %s would be skipped due to missing host path annotation", tc.pod.Name) + } + if _, ok := tc.pod.Annotations[captureConstants.CaptureFilenameAnnotationKey]; !ok { + shouldSkip = true + t.Logf("Pod %s would be skipped due to missing filename annotation", tc.pod.Name) + } + } + + if shouldSkip != tc.expectSkip { + t.Errorf("Expected skip=%v, got skip=%v for %s", tc.expectSkip, shouldSkip, tc.description) + } + + t.Logf("Test case '%s' completed: %s", tc.name, tc.description) + }) + } +} diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index 85aef2f576..7822f5f91f 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -243,6 +243,18 @@ Download capture files and specify an output location: kubectl retina capture download --name -o ``` +Download all available captures in the current namespace: + +```sh +kubectl retina capture download --all +``` + +Download all available captures from all namespaces: + +```sh +kubectl retina capture download --all --all-namespaces +``` + By default, files are downloaded to the current directory. #### Download from Blob Storage @@ -255,9 +267,11 @@ kubectl retina capture download --blob-url "" #### Download Output Structure -The command will create a directory with the capture name and download all related capture files. Each capture file is downloaded as a `.tar.gz` archive with a name pattern matching `$(capturename)-$(hostname)-$(date +%Y%m%d%H%M%S%Z).tar.gz`. +The command will create different output structures depending on the options used: + +##### Individual Capture Download -For example: +For individual capture downloads using `--name`, files are organized by capture name: ```bash /output-directory/ @@ -266,6 +280,79 @@ For example: └── capture-name-node2-20230320013600UTC.tar.gz ``` +##### All Captures Download + +When using `--all`, all captures are consolidated into a single timestamped archive: + +```bash +/output-directory/ +└── all-captures-20230320134500.tar.gz +``` + +The archive contents are organized by capture name: + +```bash +# Contents of all-captures-20230320134500.tar.gz +capture-name-1/ +├── capture-name-1-node1-20230320013600UTC.tar.gz +└── capture-name-1-node2-20230320013600UTC.tar.gz +capture-name-2/ +├── capture-name-2-node1-20230320014500UTC.tar.gz +└── capture-name-2-node2-20230320014500UTC.tar.gz +``` + +##### All Captures with All Namespaces + +When using `--all --all-namespaces`, the archive contents include namespace information: + +```bash +# Contents of all-captures-20230320134500.tar.gz +namespace-1/ +└── capture-name-1/ + ├── capture-name-1-node1-20230320013600UTC.tar.gz + └── capture-name-1-node2-20230320013600UTC.tar.gz +namespace-2/ +└── capture-name-2/ + ├── capture-name-2-node1-20230320014500UTC.tar.gz + └── capture-name-2-node2-20230320014500UTC.tar.gz +``` + +#### Download Options + +| Flag | Description | Notes | +|------|-------------|-------| +| `--name` | Download capture files for a specific capture name | Creates individual files in capture-specific directory | +| `--all` | Download all available captures in the current namespace | Creates single consolidated archive | +| `--all-namespaces` | Download captures from all namespaces (requires `--all`) | Includes namespace in archive structure | +| `--blob-url` | Download from Azure Blob Storage using SAS URL | Requires Read/List permissions | +| `-o, --output` | Specify output directory | Defaults to current directory | + +#### Examples + +Download a specific capture: + +```sh +kubectl retina capture download --name my-capture +``` + +Download all captures with custom output location: + +```sh +kubectl retina capture download --all -o /tmp/retina-downloads +``` + +Download all captures from all namespaces: + +```sh +kubectl retina capture download --all --all-namespaces +``` + +Download from blob storage: + +```sh +kubectl retina capture download --blob-url "https://mystorageaccount.blob.core.windows.net/captures?sp=rl&st=..." +``` + ## Obtaining the output After downloading or copying the tarball from the location specified, extract the tarball through the `tar` command in either Linux shell or Windows Powershell, for example, From c760215349c1afa530462958a8216ae18c2b4f2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:36:14 -0500 Subject: [PATCH 168/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.88.4 to 1.92.0 (#1947) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.88.4 to 1.92.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.88.4&new-version=1.92.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 22 +++++++++++----------- go.sum | 44 ++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index 39fad2816b..6be5345876 100644 --- a/go.mod +++ b/go.mod @@ -46,20 +46,20 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 // indirect - github.com/aws/smithy-go v1.23.0 // indirect + github.com/aws/smithy-go v1.24.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -272,10 +272,10 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.39.2 + github.com/aws/aws-sdk-go-v2 v1.40.1 github.com/aws/aws-sdk-go-v2/config v1.31.6 github.com/aws/aws-sdk-go-v2/credentials v1.18.10 - github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 diff --git a/go.sum b/go.sum index f1691f9e1e..3b50db7b7a 100644 --- a/go.sum +++ b/go.sum @@ -244,10 +244,10 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I= -github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00= +github.com/aws/aws-sdk-go-v2 v1.40.1 h1:difXb4maDZkRH0x//Qkwcfpdg1XQVXEAEs2DdXldFFc= +github.com/aws/aws-sdk-go-v2 v1.40.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ= github.com/aws/aws-sdk-go-v2/credentials v1.18.10 h1:xdJnXCouCx8Y0NncgoptztUocIYLKeQxrCgN6x9sdhg= @@ -256,38 +256,38 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 h1:wbjnrrMnKew78/juW7I2BtK github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6/go.mod h1:AtiqqNrDioJXuUgz3+3T0mBWN7Hro2n9wll2zRUc0ww= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 h1:Y5YXgygXwDI5P4RkteB5yF7v35neH7LfJKBG+hzIons= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15/go.mod h1:K+/1EpG42dFSY7CBj+Fruzm8PsCGWTXJ3jdeJ659oGQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 h1:AvltKnW9ewxX2hFmQS0FyJH93aSvJVUEFvXfU+HWtSE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15/go.mod h1:3I4oCdZdmgrREhU74qS1dK9yZ62yumob+58AbFR4cQA= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 h1:w9LnHqTq8MEdlnyhV4Bwfizd65lfNCNgdlNC6mM5paE= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9/go.mod h1:LGEP6EK4nj+bwWNdrvX/FnDTFowdBNwcSPuZu/ouFys= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 h1:NLYTEyZmVZo0Qh183sC8nC+ydJXOOeIL/qI/sS3PdLY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15/go.mod h1:Z803iB3B0bc8oJV8zH2PERLRfQUJ2n2BXISpsA4+O1M= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0 h1:X0FveUndcZ3lKbSpIC6rMYGRiQTcUVRNH6X4yYtIrlU= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0/go.mod h1:IWjQYlqw4EX9jw2g3qnEPPWvCE6bS8fKzhMed1OK7c8= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 h1:wuZ5uW2uhJR63zwNlqWH2W4aL4ZjeJP3o92/W+odDY4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9/go.mod h1:/G58M2fGszCrOzvJUkDdY8O9kycodunH4VdT5oBAqls= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 h1:P1MU/SuhadGvg2jtviDXPEejU3jBNhoeeAlRadHzvHI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6/go.mod h1:5KYaMG6wmVKMFBSfWoyG/zH8pWwzQFnKgpoSRlXHKdQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 h1:3/u/4yZOffg5jdNk1sDpOQ4Y+R6Xbh+GzpDrSZjuy3U= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15/go.mod h1:4Zkjq0FKjE78NKjabuM4tRXKFzUJWXgP0ItEZK8l7JU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 h1:wsSQ4SVz5YE1crz0Ap7VBZrV4nNqZt4CIBBT8mnwoNc= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15/go.mod h1:I7sditnFGtYMIqPRU1QoHZAUrXkGp4SczmlLwrNPlD0= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4 h1:mUI3b885qJgfqKDUSj6RgbRqLdX0wGmg8ruM03zNfQA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4/go.mod h1:6v8ukAxc7z4x4oBjGUsLnH7KGLY9Uhcgij19UJNkiMg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 h1:IrbE3B8O9pm3lsg96AXIN5MXX4pECEuExh/A0Du3AuI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0/go.mod h1:/sJLzHtiiZvs6C1RbxS/anSAFwZD6oC6M/kotQzOiLw= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 h1:8OLZnVJPvjnrxEwHFg9hVUof/P4sibH+Ea4KKuqAGSg= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1/go.mod h1:27M3BpVi0C02UiQh1w9nsBEit6pLhlaH3NHna6WUbDE= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 h1:gKWSTnqudpo8dAxqBqZnDoDWCiEh/40FziUjr/mo6uA= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2/go.mod h1:x7+rkNmRoEN1U13A6JE2fXne9EWyJy54o3n6d4mGaXQ= github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 h1:YZPjhyaGzhDQEvsffDEcpycq49nl7fiGcfJTIo8BszI= github.com/aws/aws-sdk-go-v2/service/sts v1.38.2/go.mod h1:2dIN8qhQfv37BdUYGgEC8Q3tteM3zFxTI1MLO2O3J3c= -github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE= -github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= +github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f/go.mod h1:rAE739ssmE5O5fLuQ2y8uHdmOJaelE5I0Es3SxV0y1A= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From bd91072fa950edca8d8052f964caafc1bea8cfe3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:51:57 -0500 Subject: [PATCH 169/448] deps: bump actions/checkout from 6.0.0 to 6.0.1 (#1960) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1.
Release notes

Sourced from actions/checkout's releases.

v6.0.1

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v6...v6.0.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=6.0.0&new-version=6.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/docs.yaml | 2 +- .github/workflows/e2e-test-event-writer.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 14 +++++++------- .github/workflows/kapinger.yaml | 2 +- .github/workflows/markdownlint.yaml | 2 +- .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ .github/workflows/release-validation.yaml | 2 +- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- .github/workflows/trivy.yaml | 2 +- .github/workflows/update-hubble.yaml | 2 +- 18 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index ca2cdd35d5..71c664e449 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository if: env.IS_NOT_MERGE_GROUP - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go if: env.IS_NOT_MERGE_GROUP uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 4e0ff298ff..3123f4f97e 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-node@v6 with: node-version: 20 diff --git a/.github/workflows/e2e-test-event-writer.yml b/.github/workflows/e2e-test-event-writer.yml index d0cea32c4e..964e5fe6e9 100644 --- a/.github/workflows/e2e-test-event-writer.yml +++ b/.github/workflows/e2e-test-event-writer.yml @@ -31,4 +31,4 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index c84b391a6e..8477439f11 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -86,7 +86,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 2919882677..88ef83cd8e 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -20,7 +20,7 @@ jobs: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 07eeee0593..6d366e8fda 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 - name: Set up Go @@ -35,7 +35,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 - name: Set up Go diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 1c43df4a91..99ff68e597 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -74,7 +74,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -134,7 +134,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -184,7 +184,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -233,7 +233,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -290,7 +290,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup QEMU uses: docker/setup-qemu-action@v3 @@ -318,7 +318,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 25d39044e9..8b8f358db8 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set outputs id: vars diff --git a/.github/workflows/markdownlint.yaml b/.github/workflows/markdownlint.yaml index f216de3bf7..2b42f21532 100644 --- a/.github/workflows/markdownlint.yaml +++ b/.github/workflows/markdownlint.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: DavidAnson/markdownlint-cli2-action@v9 with: command: config diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index 3834d1ca57..7cc9015d46 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index fd6affb823..75b8f366bc 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -19,7 +19,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 109a5bc4dd..ec865daefb 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -116,7 +116,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -161,7 +161,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -204,7 +204,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: @@ -254,7 +254,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index 535a450843..084f86f807 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 - name: Get latest tag id: get_latest_tag diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index b03702d912..5dfb8ade3b 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -68,7 +68,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 29db32b7b4..9e2600b2ba 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -15,7 +15,7 @@ jobs: tofu_version: 1.8.3 - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up Go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 91aefaf46b..e70edf6eac 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 43688982e4..e170645f0e 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest # trivy only supports running on Linux steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Get Tag run: | diff --git a/.github/workflows/update-hubble.yaml b/.github/workflows/update-hubble.yaml index 96fbbadb79..1ba1c06bdc 100644 --- a/.github/workflows/update-hubble.yaml +++ b/.github/workflows/update-hubble.yaml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Get latest Hubble version id: get_version From f4a818e2a70b83843d3d0227b1c438f57b82b88f Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Wed, 3 Dec 2025 07:59:47 -0800 Subject: [PATCH 170/448] feat(packetparser): Allow sampling of packets (#1767) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR allows for optional sampling of packet reporting when in high data aggregation level for `packetparser`. By default, all packets are reported but optionally `1 out of n` packets are sampled by random chance with the exception of certain important control flags or when hitting the reporting interval. This allows Retina to scale to high network volume environments at the trade-off of some reporting granularity. The performance impact of this is mostly for workloads with lots of new connections, connections already tracked in the conntrack table rely on https://github.com/microsoft/retina/pull/1665 for scalability. The behavior added in https://github.com/microsoft/retina/pull/1665 allows for accurate reporting of metrics despite sampling being in place. ## Related Issue https://github.com/microsoft/retina/issues/1760 ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ## Main Screenshot 2025-07-22 at 4 51 24 PM ## After the change (with default sampling rate of 1) Screenshot 2025-07-22 at 4 57 36 PM ## After the change (with sampling rate of 1000) Screenshot 2025-07-22 at 5 04 22 PM --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- .../helm/retina/templates/configmap.yaml | 1 + .../controller/helm/retina/values.yaml | 1 + docs/02-Installation/03-Config.md | 1 + docs/03-Metrics/plugins/Linux/packetparser.md | 8 ++ pkg/config/config.go | 12 ++- pkg/config/config_test.go | 4 +- pkg/plugin/conntrack/_cprog/conntrack.c | 94 ++++++++++++------- pkg/plugin/packetparser/_cprog/dynamic.h | 1 + pkg/plugin/packetparser/_cprog/packetparser.c | 17 +++- pkg/plugin/packetparser/packetparser_linux.go | 4 + 10 files changed, 102 insertions(+), 41 deletions(-) diff --git a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml index da0de325f2..14f197b8eb 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml @@ -25,6 +25,7 @@ data: bypassLookupIPOfInterest: {{ .Values.bypassLookupIPOfInterest }} dataAggregationLevel: {{ .Values.dataAggregationLevel }} telemetryInterval: {{ .Values.daemonset.telemetryInterval }} + dataSamplingRate: {{ .Values.dataSamplingRate }} {{- end}} --- {{- if .Values.os.windows}} diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index 6bf0c9cf60..49902e33e4 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -56,6 +56,7 @@ remoteContext: false enableAnnotations: false bypassLookupIPOfInterest: false dataAggregationLevel: "low" +dataSamplingRate: 1 imagePullSecrets: [] nameOverride: "retina" diff --git a/docs/02-Installation/03-Config.md b/docs/02-Installation/03-Config.md index 6b6df2895d..97dbac74d5 100644 --- a/docs/02-Installation/03-Config.md +++ b/docs/02-Installation/03-Config.md @@ -53,6 +53,7 @@ Apply to both Agent and Operator. * `enableAnnotations`: Enables gathering of metrics for annotated resources. Resources can be annotated with `retina.sh=observe`. Requires the operator and `operator.enableRetinaEndpoint` to be enabled. By enabling annotations, the agent will not use MetricsConfiguration CRD. * `bypassLookupIPOfInterest`: If true, plugins like `packetparser` and `dropreason` will bypass IP lookup, generating an event for each packet regardless. `enableAnnotations` will not work if this is true. * `dataAggregationLevel`: Defines the level of data aggregation for Retina. See [Data Aggregation](../05-Concepts/data-aggregation.md) for more details. +* `dataSamplingRate`: Defines the data sampling rate for `packetparser`. See [Sampling](../03-Metrics/plugins/Linux/packetparser.md#sampling) for more details. ## Operator Configuration diff --git a/docs/03-Metrics/plugins/Linux/packetparser.md b/docs/03-Metrics/plugins/Linux/packetparser.md index b772fe362a..d2a6d92618 100644 --- a/docs/03-Metrics/plugins/Linux/packetparser.md +++ b/docs/03-Metrics/plugins/Linux/packetparser.md @@ -15,6 +15,14 @@ The `packetparser` plugin requires the `CAP_NET_ADMIN` and `CAP_SYS_ADMIN` capab `packetparser` does not produce Basic metrics. In Advanced mode (refer to [Metric Modes](../../modes/modes.md)), the plugin transforms an eBPF result into an enriched `Flow` by adding Pod information based on IP. It then sends the `Flow` to an external channel, enabling *several modules* to generate Pod-Level metrics. +## Sampling + +Since `packetparser` produces many enriched `Flow` objects it can be quite expensive for user space to process. Thus, when operating in `high` [data aggregation](../../../05-Concepts/data-aggregation.md) level optional sampling for reported packets is available via the `dataSamplingRate` configuration option. + +`dataSamplingRate` is expressed in 1 out of N terms, where N is the `dataSamplingRate` value. For example, if `dataSamplingRate` is 3 1/3rd of packets will be sampled for reporting. + +Keep in mind that there are cases where reporting will happen anyways as to ensure metric accuracy. + ### Code locations - Plugin and eBPF code: *pkg/plugin/packetparser/* diff --git a/pkg/config/config.go b/pkg/config/config.go index 0ac6b1cb06..f9086ff902 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -24,8 +24,9 @@ const ( ) var ( - ErrorTelemetryIntervalTooSmall = fmt.Errorf("telemetryInterval smaller than %v is not allowed", MinTelemetryInterval) - DefaultTelemetryInterval = 15 * time.Minute + ErrorTelemetryIntervalTooSmall = fmt.Errorf("telemetryInterval smaller than %v is not allowed", MinTelemetryInterval) + DefaultTelemetryInterval = 15 * time.Minute + DefaultSamplingRate uint32 = 1 ) func (l *Level) UnmarshalText(text []byte) error { @@ -75,6 +76,7 @@ type Config struct { DataAggregationLevel Level `yaml:"dataAggregationLevel"` MonitorSockPath string `yaml:"monitorSockPath"` TelemetryInterval time.Duration `yaml:"telemetryInterval"` + DataSamplingRate uint32 `yaml:"dataSamplingRate"` } func GetConfig(cfgFilename string) (*Config, error) { @@ -122,6 +124,12 @@ func GetConfig(cfgFilename string) (*Config, error) { return nil, ErrorTelemetryIntervalTooSmall } + // If unset, default sampling rate to 1 + if config.DataSamplingRate == 0 { + log.Printf("dataSamplingRate is not set, defaulting to %v", DefaultSamplingRate) + config.DataSamplingRate = DefaultSamplingRate + } + return &config, nil } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 2d6ca3b92f..d26d6e5835 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -28,7 +28,8 @@ func TestGetConfig(t *testing.T) { c.RemoteContext || c.EnableAnnotations || c.TelemetryInterval != 15*time.Minute || - c.DataAggregationLevel != Low { + c.DataAggregationLevel != Low || + c.DataSamplingRate != 1 { t.Errorf("Expeted config should be same as ./testwith/config.yaml; instead got %+v", c) } } @@ -65,6 +66,5 @@ func TestDecodeLevelHook(t *testing.T) { result, err := decodeLevelHook(reflect.TypeOf(test.input), reflect.TypeOf(Level(0)), test.input) require.NoError(t, err) assert.Equal(t, test.expected, result) - } } diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c index be648d8198..f5fb2b3729 100644 --- a/pkg/plugin/conntrack/_cprog/conntrack.c +++ b/pkg/plugin/conntrack/_cprog/conntrack.c @@ -233,8 +233,9 @@ static __always_inline __u8 _ct_get_traffic_direction(__u8 observation_point) { * @arg key The key to be used to create the new connection. * @arg observation_point The point in the network stack where the packet is observed. * @arg is_reply true if the packet is a SYN-ACK packet. False if it is a SYN packet. + * @arg sampled Whether or not the packet was sampled for reporting. */ -static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key *key, __u8 observation_point, bool is_reply) { +static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key *key, __u8 observation_point, bool is_reply, bool sampled) { struct ct_entry new_value; __builtin_memset(&new_value, 0, sizeof(struct ct_entry)); __u64 now = bpf_mono_now(); @@ -245,14 +246,20 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru new_value.eviction_time = now + CT_SYN_TIMEOUT; if(is_reply) { new_value.flags_seen_rx_dir = p->flags; - new_value.last_report_rx_dir = now; - new_value.bytes_seen_since_last_report_rx_dir = 0; - new_value.packets_seen_since_last_report_rx_dir = 0; + new_value.last_report_rx_dir = sampled ? now : 0; + new_value.bytes_seen_since_last_report_rx_dir = !sampled ? p->bytes : 0; + new_value.packets_seen_since_last_report_rx_dir = !sampled; + if (!sampled) { + _ct_record_tcp_flags(p->flags, &new_value.flags_seen_since_last_report_rx_dir); + } } else { new_value.flags_seen_tx_dir = p->flags; - new_value.last_report_tx_dir = now; - new_value.bytes_seen_since_last_report_tx_dir = 0; - new_value.packets_seen_since_last_report_tx_dir = 0; + new_value.last_report_tx_dir = sampled ? now : 0; + new_value.bytes_seen_since_last_report_tx_dir = !sampled ? p->bytes : 0; + new_value.packets_seen_since_last_report_tx_dir = !sampled; + if (!sampled) { + _ct_record_tcp_flags(p->flags, &new_value.flags_seen_since_last_report_tx_dir); + } } new_value.is_direction_unknown = false; new_value.traffic_direction = _ct_get_traffic_direction(observation_point); @@ -273,7 +280,7 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru p->is_reply = is_reply; p->traffic_direction = new_value.traffic_direction; bpf_map_update_elem(&retina_conntrack, key, &new_value, BPF_ANY); - return true; + return sampled; } /** @@ -281,8 +288,9 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru * @arg *p pointer to the packet to be processed. * @arg key The key to be used to create the new connection. * @arg observation_point The point in the network stack where the packet is observed. + * @arg sampled Whether or not the packet was sampled for reporting. */ -static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct ct_v4_key *key, __u8 observation_point) { +static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct ct_v4_key *key, __u8 observation_point, bool sampled) { if (!p || !key) { return false; } @@ -295,9 +303,9 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c } new_value.eviction_time = now + CT_CONNECTION_LIFETIME_NONTCP; new_value.flags_seen_tx_dir = p->flags; - new_value.last_report_tx_dir = now; - new_value.bytes_seen_since_last_report_tx_dir = 0; - new_value.packets_seen_since_last_report_tx_dir = 0; + new_value.last_report_tx_dir = sampled ? now : 0; + new_value.bytes_seen_since_last_report_tx_dir = !sampled ? p->bytes : 0; + new_value.packets_seen_since_last_report_tx_dir = !sampled; new_value.traffic_direction = _ct_get_traffic_direction(observation_point); #ifdef ENABLE_CONNTRACK_METRICS new_value.conntrack_metadata.packets_tx_count = 1; @@ -310,7 +318,7 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c p->is_reply = false; p->traffic_direction = new_value.traffic_direction; bpf_map_update_elem(&retina_conntrack, key, &new_value, BPF_ANY); - return true; + return sampled; } /** @@ -319,18 +327,19 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c * @arg key The key to be used to handle the connection. * @arg reverse_key The reverse key to be used to handle the connection. * @arg observation_point The point in the network stack where the packet is observed. + * @arg sampled Whether or not the packet was sampled for reporting. */ -static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct ct_v4_key *key, struct ct_v4_key *reverse_key, __u8 observation_point) { +static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct ct_v4_key *key, struct ct_v4_key *reverse_key, __u8 observation_point, bool sampled) { if (!p || !key || !reverse_key) { return false; } u8 tcp_handshake = p->flags & (TCP_SYN|TCP_ACK); if (tcp_handshake == TCP_SYN) { // We have a SYN, we set `is_reply` to false and we provide `key` - return _ct_create_new_tcp_connection(p, key, observation_point, false); + return _ct_create_new_tcp_connection(p, key, observation_point, false, sampled); } else if(tcp_handshake == (TCP_SYN|TCP_ACK)) { // We have a SYN-ACK, we set `is_reply` to true and we provide `reverse_key` - return _ct_create_new_tcp_connection(p, reverse_key, observation_point, true); + return _ct_create_new_tcp_connection(p, reverse_key, observation_point, true, sampled); } // The packet is not a SYN packet and the connection corresponding to this packet is not found. @@ -353,9 +362,12 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c if (p->flags & TCP_ACK) { p->is_reply = true; new_value.flags_seen_rx_dir = p->flags; - new_value.last_report_rx_dir = now; - new_value.bytes_seen_since_last_report_rx_dir = 0; - new_value.packets_seen_since_last_report_rx_dir = 0; + new_value.last_report_rx_dir = sampled ? now : 0; + new_value.bytes_seen_since_last_report_rx_dir = !sampled ? p->bytes : 0; + new_value.packets_seen_since_last_report_rx_dir = !sampled; + if (!sampled) { + _ct_record_tcp_flags(p->flags, &new_value.flags_seen_since_last_report_rx_dir); + } #ifdef ENABLE_CONNTRACK_METRICS new_value.conntrack_metadata.bytes_rx_count = p->bytes; new_value.conntrack_metadata.packets_rx_count = 1; @@ -364,9 +376,12 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c } else { // Otherwise, the packet is considered as a packet in the send direction. p->is_reply = false; new_value.flags_seen_tx_dir = p->flags; - new_value.last_report_tx_dir = now; - new_value.bytes_seen_since_last_report_tx_dir = 0; - new_value.packets_seen_since_last_report_tx_dir = 0; + new_value.last_report_tx_dir = sampled ? now : 0; + new_value.bytes_seen_since_last_report_tx_dir = !sampled ? p->bytes : 0; + new_value.packets_seen_since_last_report_tx_dir = !sampled; + if (!sampled) { + _ct_record_tcp_flags(p->flags, &new_value.flags_seen_since_last_report_tx_dir); + } #ifdef ENABLE_CONNTRACK_METRICS new_value.conntrack_metadata.bytes_tx_count = p->bytes; new_value.conntrack_metadata.packets_tx_count = 1; @@ -377,7 +392,7 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c // Update packet's conntrack metadata. __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS - return true; + return sampled; } /** @@ -386,17 +401,18 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c * @arg key The key to be used to handle the connection. * @arg reverse_key The reverse key to be used to handle the connection. * @arg observation_point The point in the network stack where the packet is observed. + * @arg sampled Whether or not the packet was sampled for reporting. */ -static __always_inline struct packetreport _ct_handle_new_connection(struct packet *p, struct ct_v4_key *key, struct ct_v4_key *reverse_key, __u8 observation_point) { +static __always_inline struct packetreport _ct_handle_new_connection(struct packet *p, struct ct_v4_key *key, struct ct_v4_key *reverse_key, __u8 observation_point, bool sampled) { struct packetreport report; __builtin_memset(&report, 0, sizeof(struct packetreport)); if (!p || !key || !reverse_key) { return report; } if (key->proto & IPPROTO_TCP) { - report.report = _ct_handle_tcp_connection(p, key, reverse_key, observation_point); + report.report = _ct_handle_tcp_connection(p, key, reverse_key, observation_point, sampled); } else if (key->proto & IPPROTO_UDP) { - report.report = _ct_handle_udp_connection(p, key, observation_point); + report.report = _ct_handle_udp_connection(p, key, observation_point, sampled); } else { report.report = false; // We are not interested in other protocols. } @@ -410,9 +426,10 @@ static __always_inline struct packetreport _ct_handle_new_connection(struct pack * @arg flags The flags of the packet. * @arg direction The direction of the packet in relation to the connection. * @arg bytes The size of the packet in bytes. + * @arg sampled Whether or not the packet was sampled for reporting. * Returns a packetreport struct representing if the packet should be reported to userspace. */ -static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4_key *key, struct ct_entry *entry, __u8 flags, __u8 direction, __u32 bytes) { +static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4_key *key, struct ct_entry *entry, __u8 flags, __u8 direction, __u32 bytes, bool sampled) { struct packetreport report; __builtin_memset(&report, 0, sizeof(struct packetreport)); report.report = false; @@ -522,21 +539,27 @@ static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4 WRITE_ONCE(entry->eviction_time, now + CT_CONNECTION_LIFETIME_NONTCP); } + if (flags != seen_flags) { + if (direction == CT_PACKET_DIR_TX) { + WRITE_ONCE(entry->flags_seen_tx_dir, flags); + } else { + WRITE_ONCE(entry->flags_seen_rx_dir, flags); + } + } + // Report if: // 1. We already decided to report based on protocol-specific rules, or - // 2. New flags have appeared, or + // 2. New flags have appeared and the packet has been sampled, or // 3. Reporting interval has elapsed - if (should_report || flags != seen_flags || now - last_report >= CT_REPORT_INTERVAL) { + if (should_report || (sampled && flags != seen_flags) || now - last_report >= CT_REPORT_INTERVAL) { report.report = true; // Update the connection's state if (direction == CT_PACKET_DIR_TX) { - WRITE_ONCE(entry->flags_seen_tx_dir, flags); WRITE_ONCE(entry->last_report_tx_dir, now); WRITE_ONCE(entry->bytes_seen_since_last_report_tx_dir, 0); WRITE_ONCE(entry->packets_seen_since_last_report_tx_dir, 0); __builtin_memset(&entry->flags_seen_since_last_report_tx_dir, 0, sizeof(struct tcpflagscount)); } else { - WRITE_ONCE(entry->flags_seen_rx_dir, flags); WRITE_ONCE(entry->last_report_rx_dir, now); WRITE_ONCE(entry->bytes_seen_since_last_report_rx_dir, 0); WRITE_ONCE(entry->packets_seen_since_last_report_rx_dir, 0); @@ -565,9 +588,10 @@ static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4 * Process a packet and update the connection tracking map. * @arg *p pointer to the packet to be processed. * @arg observation_point The point in the network stack where the packet is observed. + * @arg sampled Whether or not the packet has been sampled for reporting. * Returns a packetreport struct representing if the packet should be reported to userspace. */ -static __always_inline __attribute__((unused)) struct packetreport ct_process_packet(struct packet *p, __u8 observation_point) { +static __always_inline __attribute__((unused)) struct packetreport ct_process_packet(struct packet *p, __u8 observation_point, bool sampled) { if (!p) { struct packetreport report; __builtin_memset(&report, 0, sizeof(struct packetreport)); @@ -601,7 +625,7 @@ static __always_inline __attribute__((unused)) struct packetreport ct_process_pa // Update packet's conntract metadata. __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS - return _ct_should_report_packet(&key, entry, p->flags, CT_PACKET_DIR_TX, p->bytes); + return _ct_should_report_packet(&key, entry, p->flags, CT_PACKET_DIR_TX, p->bytes, sampled); } // The connection is not found in the send direction. Check the reply direction by reversing the key. @@ -623,9 +647,9 @@ static __always_inline __attribute__((unused)) struct packetreport ct_process_pa // Update packet's conntract metadata. __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata)); #endif // ENABLE_CONNTRACK_METRICS - return _ct_should_report_packet(&reverse_key, entry, p->flags, CT_PACKET_DIR_RX, p->bytes); + return _ct_should_report_packet(&reverse_key, entry, p->flags, CT_PACKET_DIR_RX, p->bytes, sampled); } // If the connection is still not found, the connection is new. - return _ct_handle_new_connection(p, &key, &reverse_key, observation_point); + return _ct_handle_new_connection(p, &key, &reverse_key, observation_point, sampled); } diff --git a/pkg/plugin/packetparser/_cprog/dynamic.h b/pkg/plugin/packetparser/_cprog/dynamic.h index ecadc42211..43f0976f19 100644 --- a/pkg/plugin/packetparser/_cprog/dynamic.h +++ b/pkg/plugin/packetparser/_cprog/dynamic.h @@ -1,2 +1,3 @@ #define BYPASS_LOOKUP_IP_OF_INTEREST 0 #define DATA_AGGREGATION_LEVEL 0 +#define DATA_SAMPLING_RATE 1 \ No newline at end of file diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c index 07256867fb..d961c81f5c 100644 --- a/pkg/plugin/packetparser/_cprog/packetparser.c +++ b/pkg/plugin/packetparser/_cprog/packetparser.c @@ -208,11 +208,24 @@ static void parse(struct __sk_buff *skb, __u8 obs) p.conntrack_metadata = conntrack_metadata; #endif // ENABLE_CONNTRACK_METRICS + #ifdef DATA_AGGREGATION_LEVEL + + // Calculate sampling + bool sampled __attribute__((unused)); + sampled = true; + + #ifdef DATA_SAMPLING_RATE + u32 rand __attribute__((unused)); + rand = bpf_get_prandom_u32(); + if (rand >= UINT32_MAX / DATA_SAMPLING_RATE) { + sampled = false; + } + #endif + // Process the packet in ct struct packetreport report __attribute__((unused)); - report = ct_process_packet(&p, obs); + report = ct_process_packet(&p, obs, sampled); - #ifdef DATA_AGGREGATION_LEVEL // If the data aggregation level is low, always send the packet to the perf buffer. #if DATA_AGGREGATION_LEVEL == DATA_AGGREGATION_LEVEL_LOW p.previously_observed_packets = 0; diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index 9baade8e67..f6f5389962 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -117,6 +117,10 @@ func (p *packetParser) Generate(ctx context.Context) error { p.l.Info("data aggregation level", zap.String("level", p.cfg.DataAggregationLevel.String())) st += fmt.Sprintf("#define DATA_AGGREGATION_LEVEL %d\n", p.cfg.DataAggregationLevel) + // Process packetparser sampling rate. + p.l.Info("sampling rate", zap.Uint32("rate", p.cfg.DataSamplingRate)) + st += fmt.Sprintf("#define DATA_SAMPLING_RATE %d\n", p.cfg.DataSamplingRate) + // Generate dynamic header for packetparser. err = loader.WriteFile(ctx, dynamicHeaderPath, st) if err != nil { From 59c1655c07afe60ccd4d518114d750bc300a3f16 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:34:03 +0000 Subject: [PATCH 171/448] feat(cli): CLI image with bash (#1946) # Description Create cli image that supports bash ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Kamil Co-authored-by: Kamil --- Makefile | 21 +++++++++++++++++++++ cli/Dockerfile | 13 ++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 81d1d95097..3d18478709 100644 --- a/Makefile +++ b/Makefile @@ -172,6 +172,7 @@ RETINA_INIT_IMAGE = $(IMAGE_NAMESPACE)/retina-init RETINA_OPERATOR_IMAGE = $(IMAGE_NAMESPACE)/retina-operator RETINA_SHELL_IMAGE = $(IMAGE_NAMESPACE)/retina-shell KUBECTL_RETINA_IMAGE = $(IMAGE_NAMESPACE)/kubectl-retina +KUBECTL_RETINA_SHELL_IMAGE = $(IMAGE_NAMESPACE)/kubectl-retina-shell RETINA_INTEGRATION_TEST_IMAGE = $(IMAGE_NAMESPACE)/retina-integration-test RETINA_PROTO_IMAGE = $(IMAGE_NAMESPACE)/retina-proto-gen RETINA_GO_GEN_IMAGE = $(IMAGE_NAMESPACE)/retina-go-gen @@ -315,6 +316,20 @@ kubectl-retina-image: CONTEXT_DIR=$(REPO_ROOT) \ EXTRA_BUILD_ARGS=$(EXTRA_BUILD_ARGS) +kubectl-retina-shell-image: + echo "Building shell-enabled kubectl-retina for $(PLATFORM)" + set -e ; \ + $(MAKE) container-$(CONTAINER_BUILDER) \ + PLATFORM=$(PLATFORM) \ + DOCKERFILE=cli/Dockerfile \ + REGISTRY=$(IMAGE_REGISTRY) \ + IMAGE=$(KUBECTL_RETINA_SHELL_IMAGE) \ + VERSION=$(TAG) \ + TAG=$(RETINA_PLATFORM_TAG) \ + CONTEXT_DIR=$(REPO_ROOT) \ + TARGET=shell-target \ + EXTRA_BUILD_ARGS=$(EXTRA_BUILD_ARGS) + kapinger-image: docker buildx build --builder retina --platform windows/amd64 --target windows-amd64 -t $(IMAGE_REGISTRY)/$(KAPINGER_IMAGE):$(TAG)-windows-amd64 ./hack/tools/kapinger/ --push docker buildx build --builder retina --platform linux/amd64 --target linux-amd64 -t $(IMAGE_REGISTRY)/$(KAPINGER_IMAGE):$(TAG)-linux-amd64 ./hack/tools/kapinger/ --push @@ -370,6 +385,10 @@ manifest-kubectl-retina-image: $(eval FULL_IMAGE_NAME=$(IMAGE_REGISTRY)/$(KUBECTL_RETINA_IMAGE):$(TAG)) docker buildx imagetools create -t $(FULL_IMAGE_NAME) $(foreach platform,linux/amd64 linux/arm64, $(FULL_IMAGE_NAME)-$(subst /,-,$(platform))) +manifest-kubectl-retina-shell-image: + $(eval FULL_IMAGE_NAME=$(IMAGE_REGISTRY)/$(KUBECTL_RETINA_SHELL_IMAGE):$(TAG)) + docker buildx imagetools create -t $(FULL_IMAGE_NAME) $(foreach platform,linux/amd64 linux/arm64, $(FULL_IMAGE_NAME)-$(subst /,-,$(platform))) + manifest: echo "Building for $(COMPONENT)" if [ "$(COMPONENT)" = "retina" ]; then \ @@ -380,6 +399,8 @@ manifest: $(MAKE) manifest-shell-image; \ elif [ "$(COMPONENT)" = "kubectl-retina" ]; then \ $(MAKE) manifest-kubectl-retina-image; \ + elif [ "$(COMPONENT)" = "kubectl-retina-shell" ]; then \ + $(MAKE) manifest-kubectl-retina-shell-image; \ fi ##@ Tests diff --git a/cli/Dockerfile b/cli/Dockerfile index 4a59383145..7b7c7651c7 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -22,8 +22,19 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ -X "github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName"="$AGENT_IMAGE_NAME"" \ -a -o kubectl-retina cli/main.go +# Target 1: Distroless (secure, minimal) # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS distroless-target WORKDIR / COPY --from=builder /workspace/kubectl-retina . +# Target 2: Shell-enabled (operational, init container support) +# skopeo inspect docker://mcr.microsoft.com/cbl-mariner/base/core:2.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/cbl-mariner/base/core@sha256:4d97d662d71c1fda938ed9df36d8f490d9107cff37e89c0efa932d073285ad85 AS shell-target +WORKDIR / +COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina +RUN chmod +x /bin/kubectl-retina + +# Default target (distroless for backward compatibility) +FROM distroless-target + From a52298b985b3af1b07073b14c0a7d8ba1dc6cb38 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Mon, 8 Dec 2025 11:23:38 +0000 Subject: [PATCH 172/448] fix: add enricher ip check (#1959) # Description * created private function to create enricher (non singleton), to allow creation of enricher in new tests * public interface still creates a singleton (no logic change) * Add check if IP is nil to enricher * Add test * Refactor existing test ## Related Issue #1909 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Prometheus metrics: image Agent pod log: ```bash Defaulted container "retina" out of: retina, init-retina (init) Starting Retina Agent starting Retina daemon with legacy control plane v1.0.0-rc5-17-g2c1764d init client-go api server: https://lx-non-cil-lx-non-cilium-9b8218-51dc7ale.hcp.uksouth.azmk8s.io:443 init logger ts=2025-12-08T09:52:04.625Z level=info caller=metrics/metrics.go:198 msg="Metrics initialized" ts=2025-12-08T09:52:04.625Z level=info caller=standard/daemon.go:142 msg="{data aggregation level 15 0 low }" ts=2025-12-08T09:52:04.625Z level=info caller=standard/daemon.go:160 msg="telemetry disabled" ts=2025-12-08T09:52:04.625Z level=info caller=standard/daemon.go:178 msg="Remote context is disabled, only pods deployed on the same node as retina-agent will be monitored" ts=2025-12-08T09:52:04.625Z level=info caller=standard/daemon.go:199 msg="pod selector when remote context is disabled{pod selector 15 0 spec.nodeName=aks-nodepool1-24136058-vmss000000,status.podIP!=10.224.0.5 }" ts=2025-12-08T09:52:04.701Z level=info caller=standard/daemon.go:231 msg="Kubernetes server version: v1.33.5" ts=2025-12-08T09:52:04.701Z level=info caller=standard/daemon.go:253 msg="Initializing Pod controller" ts=2025-12-08T09:52:04.702Z level=info caller=pod/controller.go:89 msg="Setting up Pod controller" ts=2025-12-08T09:52:04.702Z level=info caller=standard/daemon.go:269 msg="Initializing Node controller" ts=2025-12-08T09:52:04.702Z level=info caller=node/controller.go:94 msg="Setting up Node controller" ts=2025-12-08T09:52:04.702Z level=info caller=standard/daemon.go:275 msg="Initializing Service controller" ts=2025-12-08T09:52:04.702Z level=info caller=service/controller.go:95 msg="Setting up Service controller" ts=2025-12-08T09:52:04.702Z level=info caller=standard/daemon.go:282 msg="Initializing MetricsConfig namespaceController" ts=2025-12-08T09:52:04.702Z level=info caller=namespace/namespace_controller.go:105 msg="Setting up Namespace controller" ts=2025-12-08T09:52:04.702Z level=info caller=pluginmanager/pluginmanager.go:55 msg="plugin manager has pod level enabled" ts=2025-12-08T09:52:04.702Z level=info caller=controllermanager/controllermanager.go:72 msg="Initializing controller manager ..." ts=2025-12-08T09:52:04.702Z level=info caller=servermanager/servermanager.go:33 msg="Initializing HTTP server ..." ts=2025-12-08T09:52:04.702Z level=info caller=server/server.go:42 msg="Setting up handlers" ts=2025-12-08T09:52:04.702Z level=info caller=server/server.go:57 msg="Completed handler setup" ts=2025-12-08T09:52:04.702Z level=info caller=servermanager/servermanager.go:37 msg="HTTP server initialized..." ts=2025-12-08T09:52:04.702Z level=info caller=standard/daemon.go:314 msg="Started controller manager" ts=2025-12-08T09:52:04.702Z level=info caller=servermanager/servermanager.go:42 msg="Starting HTTP server ..." host=0.0.0.0 port=10093 ts=2025-12-08T09:52:04.702Z level=info caller=server/server.go:69 msg="starting HTTP server... on " addr=0.0.0.0:10093 ts=2025-12-08T09:52:04.702Z level=info caller=pluginmanager/pluginmanager.go:118 msg="Starting plugin manager ..." ts=2025-12-08T09:52:04.702Z level=info caller=pluginmanager/pluginmanager.go:130 msg="starting watchers" ts=2025-12-08T09:52:04.702Z level=info caller=watchermanager/watchermanager.go:44 msg="watcher started" watcher_type=*endpoint.EndpointWatcher ts=2025-12-08T09:52:04.702Z level=info caller=watchermanager/watchermanager.go:44 msg="watcher started" watcher_type=*apiserver.ApiServerWatcher ts=2025-12-08T09:52:04.703Z level=info caller=server/server.go:208 msg="Starting metrics server" ts=2025-12-08T09:52:04.703Z level=info caller=manager/server.go:83 msg="starting server" name="health probe" addr=[::]:18081 ts=2025-12-08T09:52:04.703Z level=info caller=server/server.go:247 msg="Serving metrics server" bindAddress=:18080 secure=false ts=2025-12-08T09:52:04.703Z level=info caller=linuxutil/linuxutil_linux.go:48 msg="Initializing linuxutil plugin..." ts=2025-12-08T09:52:04.703Z level=info caller=pluginmanager/pluginmanager.go:110 msg="Reconciled plugin" name=linuxutil ts=2025-12-08T09:52:04.703Z level=info caller=dns/dns_linux.go:86 msg="Stopped dns plugin" ts=2025-12-08T09:52:04.703Z level=info caller=controller/controller.go:204 msg="Starting EventSource" controller=node controllerGroup= controllerKind=Node source="kind source: *v1.Node" ts=2025-12-08T09:52:04.703Z level=info caller=controller/controller.go:204 msg="Starting EventSource" controller=service controllerGroup= controllerKind=Service source="kind source: *v1.Service" ts=2025-12-08T09:52:04.703Z level=info caller=conntrack/conntrack_linux.go:106 msg="Starting Conntrack GC loop" ts=2025-12-08T09:52:04.703Z level=info caller=controller/controller.go:204 msg="Starting EventSource" controller=pod controllerGroup= controllerKind=Pod source="kind source: *v1.Pod" ts=2025-12-08T09:52:04.703Z level=info caller=controller/controller.go:204 msg="Starting EventSource" controller=namespace controllerGroup= controllerKind=Namespace source="kind source: *v1.Namespace" ts=2025-12-08T09:52:04.703Z level=info caller=pluginmanager/pluginmanager.go:167 msg="starting plugin linuxutil" ts=2025-12-08T09:52:04.703Z level=info caller=linuxutil/linuxutil_linux.go:63 msg="Running linuxutil plugin..." ts=2025-12-08T09:52:04.717Z level=info caller=dns/dns_linux.go:60 msg="Initialized dns plugin" ts=2025-12-08T09:52:04.717Z level=info caller=pluginmanager/pluginmanager.go:110 msg="Reconciled plugin" name=dns ts=2025-12-08T09:52:04.717Z level=info caller=packetparser/packetparser_linux.go:117 msg="data aggregation level" level=low ts=2025-12-08T09:52:04.717Z level=info caller=pluginmanager/pluginmanager.go:167 msg="starting plugin dns" ts=2025-12-08T09:52:04.717Z level=info caller=packetparser/packetparser_linux.go:125 msg="PacketParser header generated at" path=/go/src/github.com/microsoft/retina/pkg/plugin/packetparser/_cprog/dynamic.h ts=2025-12-08T09:52:04.803Z level=info caller=controller/controller.go:239 msg="Starting Controller" controller=pod controllerGroup= controllerKind=Pod ts=2025-12-08T09:52:04.803Z level=info caller=controller/controller.go:248 msg="Starting workers" controller=pod controllerGroup= controllerKind=Pod worker count=1 ts=2025-12-08T09:52:04.803Z level=info caller=controller/controller.go:239 msg="Starting Controller" controller=node controllerGroup= controllerKind=Node ts=2025-12-08T09:52:04.803Z level=info caller=controller/controller.go:248 msg="Starting workers" controller=node controllerGroup= controllerKind=Node worker count=1 ts=2025-12-08T09:52:04.803Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=kube-system/microsoft-defender-collector-ds-hrs4s ts=2025-12-08T09:52:04.804Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=kube-system/microsoft-defender-publisher-ds-49k77 ts=2025-12-08T09:52:04.804Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=kube-system/prometheus-kube-prometheus-operator-64cf9f887f-2grmj ts=2025-12-08T09:52:04.804Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=gatekeeper-system/gatekeeper-controller-f465c8d88-5ktwr ts=2025-12-08T09:52:04.804Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=kube-system/alertmanager-prometheus-kube-prometheus-alertmanager-0 ts=2025-12-08T09:52:04.804Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=kube-system/azure-policy-webhook-79f4f8b5b6-nvrrh ts=2025-12-08T09:52:04.804Z level=info caller=pod/controller.go:39 msg="Reconciling Pod" Pod=kube-system/metrics-server-5554f5bfbd-lxrtg ts=2025-12-08T09:52:04.816Z level=info caller=controller/controller.go:239 msg="Starting Controller" controller=namespace controllerGroup= controllerKind=Namespace ts=2025-12-08T09:52:04.816Z level=info caller=controller/controller.go:248 msg="Starting workers" controller=namespace controllerGroup= controllerKind=Namespace worker count=1 ts=2025-12-08T09:52:04.816Z level=info caller=controller/controller.go:239 msg="Starting Controller" controller=service controllerGroup= controllerKind=Service ts=2025-12-08T09:52:04.816Z level=info caller=controller/controller.go:248 msg="Starting workers" controller=service controllerGroup= controllerKind=Service worker count=1 ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:157 msg="Reconciling metric module" spec= specError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:346 msg="Appending namespaces to include list" namespaces= ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:361 msg="Current included namespaces" namespaces= namespacesError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:380 msg="Namespaces to add" namespaces= ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:381 msg="Namespaces to remove" namespaces= ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:346 msg="Appending namespaces to include list" namespaces= ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:361 msg="Current included namespaces" namespaces= namespacesError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:380 msg="Namespaces to add" namespaces= ts=2025-12-08T09:52:05.702Z level=info caller=metrics/metrics_module.go:381 msg="Namespaces to remove" namespaces= ts=2025-12-08T09:52:05.702Z level=info caller=metrics/forward.go:43 msg="Creating forward count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/forward.go:43 msg="Creating forward count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/drops.go:38 msg="Creating drop count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/drops.go:38 msg="Creating drop count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/tcpflags.go:37 msg="Creating TCP Flags count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/tcpretrans.go:37 msg="Creating TCP retransmit count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/dns.go:44 msg="Creating DNS count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/dns.go:44 msg="Creating DNS count metrics" options= optionsError="unsupported value type" ts=2025-12-08T09:52:05.702Z level=info caller=metrics/tcpretrans.go:57 msg="src labels" labels=direction,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.702Z level=info caller=metrics/dns.go:76 msg="src labels" labels=query_type,query,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.702Z level=info caller=metrics/dns.go:91 msg="src labels" labels=return_code,query_type,query,response,num_response,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.702Z level=info caller=metrics/forward.go:80 msg="src labels" labels=direction,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.702Z level=info caller=metrics/forward.go:80 msg="src labels" labels=direction,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.702Z level=info caller=metrics/drops.go:72 msg="src labels" labels=reason,direction,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.703Z level=info caller=metrics/drops.go:72 msg="src labels" labels=reason,direction,ip,namespace,podname,workload_kind,workload_name ts=2025-12-08T09:52:05.738Z level=info caller=packetparser/packetparser_linux.go:163 msg="PacketParser metric compiled" ts=2025-12-08T09:52:05.739Z level=info caller=packetparser/packetparser_linux.go:290 msg="Stopping packet parser" ts=2025-12-08T09:52:05.739Z level=info caller=packetparser/packetparser_linux.go:332 msg="Stopped packet parser" ts=2025-12-08T09:52:06.559Z level=info caller=common/common_linux.go:79 msg="perf reader created" Map=PerfEventArray(retina_packetparser_events)#35 PageSize=4096 BufferSize=131072 ts=2025-12-08T09:52:06.559Z level=info caller=pluginmanager/pluginmanager.go:110 msg="Reconciled plugin" name=packetparser ts=2025-12-08T09:52:06.559Z level=info caller=pluginmanager/pluginmanager.go:167 msg="starting plugin packetparser" ts=2025-12-08T09:52:06.559Z level=info caller=packetparser/packetparser_linux.go:239 msg="Starting packet parser" ts=2025-12-08T09:52:06.559Z level=info caller=packetparser/packetparser_linux.go:241 msg="setting up enricher since pod level is enabled" ts=2025-12-08T09:52:06.559Z level=info caller=packetparser/packetparser_linux.go:261 msg="Attaching bpf program to default interface of k8s Node in node namespace" ts=2025-12-08T09:52:06.560Z level=info caller=packetparser/packetparser_linux.go:272 msg="Attaching Packetparser" outgoingLink.Index=2 outgoingLink.Name=eth0 outgoingLink.HardwareAddr=7c:ed:8d:99:17:be ts=2025-12-08T09:52:06.724Z level=info caller=packetparser/packetparser_linux.go:543 msg="Started packet parser" ts=2025-12-08T09:52:07.534Z level=info caller=dropreason/dropreason_linux.go:125 msg="DropReason metric compiled" ts=2025-12-08T09:52:07.535Z level=info caller=dropreason/ebpfsetup_linux.go:69 msg="Distro check:" isMariner=false ts=2025-12-08T09:52:07.535Z level=info caller=dropreason/ebpfsetup_linux.go:78 msg="Detected kernel" version=5.15.0 ts=2025-12-08T09:52:07.535Z level=info caller=dropreason/ebpfsetup_linux.go:82 msg="Ftrace status" enabled=true ts=2025-12-08T09:52:07.922Z level=info caller=common/common_linux.go:79 msg="perf reader created" Map=PerfEventArray(retina_dropreason_events)#56 PageSize=4096 BufferSize=65536 ts=2025-12-08T09:52:08.120Z level=info caller=dropreason/ebpfsetup_linux.go:124 msg="Attached kprobe" program=__nf_conntrack_confirm ts=2025-12-08T09:52:08.146Z level=info caller=dropreason/ebpfsetup_linux.go:124 msg="Attached kprobe" program=inet_csk_accept ts=2025-12-08T09:52:08.232Z level=info caller=dropreason/ebpfsetup_linux.go:124 msg="Attached kprobe" program=nf_hook_slow ts=2025-12-08T09:52:08.321Z level=info caller=dropreason/ebpfsetup_linux.go:124 msg="Attached kprobe" program=nf_nat_inet_fn ts=2025-12-08T09:52:08.422Z level=info caller=dropreason/ebpfsetup_linux.go:137 msg="Attached kretprobe" program=nf_hook_slow ts=2025-12-08T09:52:08.457Z level=info caller=dropreason/ebpfsetup_linux.go:137 msg="Attached kretprobe" program=inet_csk_accept ts=2025-12-08T09:52:08.541Z level=info caller=dropreason/ebpfsetup_linux.go:137 msg="Attached kretprobe" program=tcp_v4_connect ts=2025-12-08T09:52:08.717Z level=info caller=dropreason/ebpfsetup_linux.go:137 msg="Attached kretprobe" program=nf_nat_inet_fn ts=2025-12-08T09:52:08.830Z level=info caller=dropreason/ebpfsetup_linux.go:137 msg="Attached kretprobe" program=__nf_conntrack_confirm ts=2025-12-08T09:52:08.831Z level=info caller=pluginmanager/pluginmanager.go:110 msg="Reconciled plugin" name=dropreason ts=2025-12-08T09:52:08.831Z level=info caller=pluginmanager/pluginmanager.go:167 msg="starting plugin dropreason" ts=2025-12-08T09:52:08.831Z level=info caller=dropreason/dropreason_linux.go:182 msg="Start listening for drop reason events..." ts=2025-12-08T09:52:08.831Z level=info caller=packetforward/packetforward_linux.go:104 msg="Packet forwarding metric header generated" ts=2025-12-08T09:52:08.831Z level=info caller=dropreason/dropreason_linux.go:188 msg="setting up enricher since pod level is enabled" ts=2025-12-08T09:52:09.538Z level=info caller=packetforward/packetforward_linux.go:132 msg="Packet forwarding metric compiled" ts=2025-12-08T09:52:09.539Z level=info caller=packetforward/packetforward_linux.go:173 msg="Packet forwarding metric initialized" ts=2025-12-08T09:52:09.539Z level=info caller=pluginmanager/pluginmanager.go:110 msg="Reconciled plugin" name=packetforward ts=2025-12-08T09:52:09.539Z level=info caller=pluginmanager/pluginmanager.go:173 msg="successfully started pluginmanager" ts=2025-12-08T09:52:09.539Z level=info caller=pluginmanager/pluginmanager.go:167 msg="starting plugin packetforward" ts=2025-12-08T09:52:09.539Z level=info caller=packetforward/packetforward_linux.go:178 msg="Start collecting packet forward metrics" ts=2025-12-08T09:52:34.743Z level=info caller=log/warning_handler.go:65 msg="v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice" ts=2025-12-08T09:52:34.747Z level=info caller=apiserver/apiserver.go:131 msg="New Apiserver IPs:" ip=4.250.221.129 ts=2025-12-08T09:52:34.747Z level=info caller=apiserver/apiserver.go:131 msg="New Apiserver IPs:" ip=10.0.0.1 ts=2025-12-08T09:53:04.713Z level=info caller=log/warning_handler.go:65 msg="v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice" ts=2025-12-08T09:53:34.716Z level=info caller=log/warning_handler.go:65 msg="v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice" ts=2025-12-08T09:54:04.715Z level=info caller=log/warning_handler.go:65 msg="v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice" ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos --- pkg/enricher/enricher.go | 41 +++++--- pkg/enricher/enricher_test.go | 176 +++++++++++++++++++++++++--------- 2 files changed, 159 insertions(+), 58 deletions(-) diff --git a/pkg/enricher/enricher.go b/pkg/enricher/enricher.go index 98013cd2ca..122d5819a1 100644 --- a/pkg/enricher/enricher.go +++ b/pkg/enricher/enricher.go @@ -40,23 +40,28 @@ type Enricher struct { outputRing *container.Ring } -func New(ctx context.Context, cache cache.CacheInterface) *Enricher { +func New(ctx context.Context, c cache.CacheInterface) *Enricher { once.Do(func() { - ir := container.NewRing(container.Capacity1023) - e = &Enricher{ - ctx: ctx, - l: log.Logger().Named("enricher"), - cache: cache, - inputRing: ir, - Reader: container.NewRingReader(ir, ir.OldestWrite()), - outputRing: container.NewRing(container.Capacity1023), - } - initialized = true + e = newEnricher(ctx, c) }) return e } +func newEnricher(ctx context.Context, c cache.CacheInterface) *Enricher { + ir := container.NewRing(container.Capacity1023) + enricher := &Enricher{ + ctx: ctx, + l: log.Logger().Named("enricher"), + cache: c, + inputRing: ir, + Reader: container.NewRingReader(ir, ir.OldestWrite()), + outputRing: container.NewRing(container.Capacity1023), + } + initialized = true + return enricher +} + func Instance() *Enricher { return e } @@ -100,7 +105,21 @@ func (e *Enricher) Run() { // enrich takes the flow and enriches it with the information from the cache func (e *Enricher) enrich(ev *v1.Event) { + if ev == nil { + e.l.Debug("received nil event to enrich") + return + } + flow := ev.Event.(*flow.Flow) + if flow == nil { + e.l.Debug("received nil flow to enrich", zap.Any("event", ev)) + return + } + + if flow.GetIP() == nil { + e.l.Debug("flow IP is nil", zap.Any("flow", flow)) + return + } // IPversion is a enum in the flow proto // 0: IPVersion_IP_NOT_USED diff --git a/pkg/enricher/enricher_test.go b/pkg/enricher/enricher_test.go index cd05556d10..f68cbc9965 100644 --- a/pkg/enricher/enricher_test.go +++ b/pkg/enricher/enricher_test.go @@ -22,6 +22,118 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" ) +var ( + // number of events + eventsGeneratedCount = 5 + + // construct the endpoints + sourcePod = common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{ + IPv4: net.IPv4(1, 1, 1, 1), + OtherIPv4s: []net.IP{net.IPv4(1, 1, 1, 2)}, + }) + destPod = common.NewRetinaEndpoint("pod2", "ns2", &common.IPAddresses{ + IPv4: net.IPv4(2, 2, 2, 2), + OtherIPv4s: []net.IP{net.IPv4(2, 2, 2, 3)}, + }) + // sourceIP = sourcePod.NetIPs().IPv4.String() + // destIP = destPod.NetIPs().IPv4.String() + sourceIP = sourcePod.NetIPs().OtherIPv4s[0].String() + destIP = destPod.NetIPs().OtherIPv4s[0].String() + + // construct events + normal = &v1.Event{ + Timestamp: timestamppb.Now(), + Event: &flow.Flow{ + Time: timestamppb.Now(), + IP: &flow.IP{ + IpVersion: 1, + Source: sourceIP, + Destination: destIP, + }, + }, + } + nilFlow = &v1.Event{ + Timestamp: timestamppb.Now(), + Event: nil, + } + nilIP = &v1.Event{ + Timestamp: timestamppb.Now(), + Event: &flow.Flow{ + Time: timestamppb.Now(), + IP: nil, + }, + } + events = []*v1.Event{ + normal, nilFlow, nilIP, + } +) + +func writeEventToEnricher(t *testing.T, e *Enricher, ev *v1.Event) { + t.Helper() + var wg sync.WaitGroup + wg.Add(1) + go func() { + for range eventsGeneratedCount { + l := log.Logger().Named("addev") + l.Info("Adding event", zap.Any("event", ev)) + time.Sleep(100 * time.Millisecond) + e.Write(ev) + } + wg.Done() + }() + e.Run() + wg.Wait() +} + +func TestEnricher(t *testing.T) { + opts := log.GetDefaultLogOpts() + opts.Level = "debug" + _, err := log.SetupZapLogger(opts) + require.NoError(t, err) + + c := cache.New(pubsub.New()) + + err = c.UpdateRetinaEndpoint(sourcePod) + require.NoError(t, err) + + err = c.UpdateRetinaEndpoint(destPod) + require.NoError(t, err) + + e := newEnricher(context.Background(), c) + + var wg sync.WaitGroup + defer wg.Wait() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + for _, ev := range events { + writeEventToEnricher(t, e, ev) + } + + l := log.Logger().Named("test-enricher") + + l.Info("Starting to read from enricher") + wg.Add(1) + go func() { + oreader := e.ExportReader() + for { + ev := oreader.NextFollow(ctx) + if ev == nil { + l.Info("No more events to read from enricher") + break + } + + l.Info("One Received event", zap.Any("event", ev)) + assertEqualEndpoint(t, sourcePod, ev.Event.(*flow.Flow).GetSource()) + assertEqualEndpoint(t, destPod, ev.Event.(*flow.Flow).GetDestination()) + } + wg.Done() + }() + + time.Sleep(3 * time.Second) +} + func TestEnricherSecondaryIPs(t *testing.T) { evCount := 20 // by design per ring, the last written item is not readable @@ -37,52 +149,25 @@ func TestEnricherSecondaryIPs(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) c := cache.New(pubsub.New()) - // construct the source endpoint - sourceEndpoints := common.NewRetinaEndpoint("pod1", "ns1", nil) - sourceEndpoints.SetLabels(map[string]string{ - "app": "app1", - }) - - sourceEndpoints.SetOwnerRefs([]*common.OwnerReference{ - { - Kind: "Pod", - Name: "pod1-deployment", - }, - }) - - sourceEndpoints.SetIPs(&common.IPAddresses{ - IPv4: net.IPv4(1, 1, 1, 1), - OtherIPv4s: []net.IP{net.IPv4(1, 1, 1, 2)}, - }) - err := c.UpdateRetinaEndpoint(sourceEndpoints) + err := c.UpdateRetinaEndpoint(sourcePod) require.NoError(t, err) - // construct the destination endpoint - destEndpoints := common.NewRetinaEndpoint("pod2", "ns2", nil) - destEndpoints.SetLabels(map[string]string{"app": "app2"}) - destEndpoints.SetOwnerRefs([]*common.OwnerReference{ - { - Kind: "Pod", - Name: "pod2-deployment", - }, - }) - destEndpoints.SetIPs(&common.IPAddresses{ - IPv4: net.IPv4(2, 2, 2, 2), - OtherIPv4s: []net.IP{net.IPv4(2, 2, 2, 3)}, - }) - err = c.UpdateRetinaEndpoint(destEndpoints) + err = c.UpdateRetinaEndpoint(destPod) require.NoError(t, err) - // get the enricher - e := New(ctx, c) + // create new enricher (not using singleton here) + e := newEnricher(ctx, c) var wg sync.WaitGroup wg.Add(1) go func() { for i := 0; i < evCount; i++ { // The Event Source IP is the secondary IP of the source endpoint + secondarySourceIP := sourcePod.NetIPs().OtherIPv4s[0].String() // The Event Destination IP is the secondary IP of the destination endpoint - addEvent(e, "1.1.1.2", "2.2.2.3") + secondaryDestIP := destPod.NetIPs().OtherIPv4s[0].String() + + addEvent(e, secondarySourceIP, secondaryDestIP) } wg.Done() }() @@ -101,12 +186,8 @@ func TestEnricherSecondaryIPs(t *testing.T) { l.Info("One Received event", zap.Any("event", ev)) // check whether the event is enriched correctly - sourceFlowEndPoint := ev.Event.(*flow.Flow).GetSource() - assert.Equal(t, sourceEndpoints.Namespace(), sourceFlowEndPoint.GetNamespace()) - assert.Equal(t, sourceEndpoints.Name(), sourceFlowEndPoint.GetPodName()) - destFlowEndPoint := ev.Event.(*flow.Flow).GetDestination() - assert.Equal(t, destEndpoints.Namespace(), destFlowEndPoint.GetNamespace()) - assert.Equal(t, destEndpoints.Name(), destFlowEndPoint.GetPodName()) + assertEqualEndpoint(t, sourcePod, ev.Event.(*flow.Flow).GetSource()) + assertEqualEndpoint(t, destPod, ev.Event.(*flow.Flow).GetDestination()) count++ } assert.Equal(t, expectedOutputCount, count, "one") @@ -123,12 +204,8 @@ func TestEnricherSecondaryIPs(t *testing.T) { break } // check whether the event is enriched correctly - sourceFlowEndPoint := ev.Event.(*flow.Flow).GetSource() - assert.Equal(t, sourceEndpoints.Namespace(), sourceFlowEndPoint.GetNamespace()) - assert.Equal(t, sourceEndpoints.Name(), sourceFlowEndPoint.GetPodName()) - destFlowEndPoint := ev.Event.(*flow.Flow).GetDestination() - assert.Equal(t, destEndpoints.Namespace(), destFlowEndPoint.GetNamespace()) - assert.Equal(t, destEndpoints.Name(), destFlowEndPoint.GetPodName()) + assertEqualEndpoint(t, sourcePod, ev.Event.(*flow.Flow).GetSource()) + assertEqualEndpoint(t, destPod, ev.Event.(*flow.Flow).GetDestination()) count++ } assert.Equal(t, expectedOutputCount, count, "two") @@ -157,3 +234,8 @@ func addEvent(e *Enricher, sourceIP, destIP string) { time.Sleep(100 * time.Millisecond) e.Write(ev) } + +func assertEqualEndpoint(t *testing.T, expected *common.RetinaEndpoint, actual *flow.Endpoint) { + assert.Equal(t, expected.Namespace(), actual.GetNamespace()) + assert.Equal(t, expected.Name(), actual.GetPodName()) +} From 5787b9903bfd33ab5ec00b26a9a3a7d2449bd49f Mon Sep 17 00:00:00 2001 From: Mereta Date: Mon, 8 Dec 2025 11:28:20 +0000 Subject: [PATCH 173/448] deps(fix-cve): Bump GoLang version & deps (#1963) # Description `selinux v1.11.0 -> selinux v1.13.1` `containerd v1.7.27 -> containerd v1.7.29` `GoLang 1.24.6 -> 1.24.11` Still have Hubble CVE we're on latest Hubble release right now 1.18.3: https://github.com/cilium/hubble/tags image ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: mereta --- cli/Dockerfile | 4 ++-- controller/Dockerfile | 4 ++-- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-2019 | 4 ++-- controller/Dockerfile.windows-2022 | 4 ++-- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 4 ++-- go.mod | 8 ++++---- go.sum | 12 ++++++------ hack/tools/kapinger/Dockerfile | 2 +- hack/tools/toolbox/Dockerfile | 2 +- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2019 | 4 ++-- operator/Dockerfile.windows-2022 | 4 ++-- test/image/Dockerfile | 4 ++-- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 7b7c7651c7..b13122dcd5 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index 7285a7653d..1558af560d 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -2,8 +2,8 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 9ccf8822b6..198ad63ed4 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index e8d7f37da2..d331466dba 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index 1e26fec9b6..a214f85bf9 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder # Build args ARG VERSION diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index d3277af81c..f5bcb94744 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder # Build args ARG VERSION diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 91a2398da3..8e6c83ea3c 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:c5acaeb9bed15c7c3d7f5ed73d2b56c76ce5efa09e498bbb2e7f7f9a6d2559f2 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:2ab8d921bd819de69bddf5ac78c7e117055492eb36a2fed0c93851514a4587d8 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index d5e7f37c21..a08c0966ea 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:c5acaeb9bed15c7c3d7f5ed73d2b56c76ce5efa09e498bbb2e7f7f9a6d2559f2 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:2ab8d921bd819de69bddf5ac78c7e117055492eb36a2fed0c93851514a4587d8 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/go.mod b/go.mod index 6be5345876..4505de7861 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/microsoft/retina -go 1.24.6 +go 1.24.11 require ( github.com/go-chi/chi/v5 v5.2.2 @@ -69,7 +69,7 @@ require ( github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect - github.com/containerd/containerd v1.7.27 // indirect + github.com/containerd/containerd v1.7.29 // indirect github.com/containerd/continuity v0.4.4 // indirect github.com/containerd/errdefs v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect @@ -79,7 +79,7 @@ require ( github.com/containernetworking/cni v1.2.3 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/cyphar/filepath-securejoin v0.5.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v26.0.0+incompatible // indirect @@ -170,7 +170,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect - github.com/opencontainers/selinux v1.11.0 // indirect + github.com/opencontainers/selinux v1.13.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.2-0.20180312054125-0646ccaebea1+incompatible // indirect diff --git a/go.sum b/go.sum index 3b50db7b7a..fd1a0a8d05 100644 --- a/go.sum +++ b/go.sum @@ -418,8 +418,8 @@ github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2 github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII= -github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0= +github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE= +github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= @@ -454,8 +454,8 @@ github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= -github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48= +github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -1201,8 +1201,8 @@ github.com/opencontainers/runc v1.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19o github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= -github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE= +github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index d6661b957e..141e36db9e 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.6 AS builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.11 AS builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index f4c839736b..6afb47f4a8 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.6 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.11 AS build ADD . . WORKDIR /go/toolbox/ RUN CGO_ENABLED=0 GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 4790b48505..6b42ca0940 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index f201fa01f1..5c1e679364 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder # Build args ARG VERSION diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index c8af57125f..6f90bed698 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 57813ad0ea..9516478daf 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.6-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:da2126cc938c2ced6d2b5e786b705e6a5241995d7a157e467c30b001cdcff915 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder ENV CGO_ENABLED=0 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 2935c0de62bbd579811cb4d956099ccc5ec71822 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:28:30 +0000 Subject: [PATCH 174/448] docs(perf): Considerations for packetparser on high-core-count systems (#1965) ## Summary Documents community-reported performance considerations when running the `packetparser` plugin on high-core-count systems (32+ cores) under sustained network load. ## Changes - **packetparser.md**: Added performance considerations section with user-reported observations, current implementation details (PERF_EVENT_ARRAY), and mitigation options - **intro.md**: Added known limitations section highlighting performance considerations on large nodes - **architecture.md**: Added note about data transfer mechanisms and their performance implications - **performance.md**: New troubleshooting guide with diagnostic steps and mitigation options - **README.md**: Added performance warning in known limitations section ## Key Points - Acknowledges these are community user reports, not independently verified by maintainers - Accurately reflects current implementation (only supports perf arrays, no ring buffer support yet) - References external analysis ([blog post](https://blog.zmalik.dev/p/who-will-observe-the-observability) and [KubeCon talk](https://www.youtube.com/watch?v=J-Zx64mJzVk)) in packetparser.md only - Provides actionable guidance: use Basic metrics, enable sampling, monitor impact - Notes that the team is evaluating options for future releases ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- README.md | 4 + docs/01-Introduction/01-intro.md | 15 ++ docs/01-Introduction/02-architecture.md | 2 + docs/03-Metrics/plugins/Linux/packetparser.md | 33 ++++ docs/06-Troubleshooting/performance.md | 176 ++++++++++++++++++ site/package-lock.json | 33 +--- 6 files changed, 231 insertions(+), 32 deletions(-) create mode 100644 docs/06-Troubleshooting/performance.md diff --git a/README.md b/README.md index 7a28679dd0..caa68e427b 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,10 @@ Retina lets you **investigate network issues on-demand** and **continuously moni See [retina.sh](http://retina.sh) for documentation and examples. +## Known Limitations + +⚠️ **Performance on High-Core-Count Systems**: Community users have reported performance considerations when using Advanced metrics (with `packetparser` plugin) on nodes with 32+ CPU cores under high network load. Consider starting with Basic metrics mode on large node types. See [Known Limitations](https://retina.sh/docs/Introduction/intro#known-limitations) for details. + ## Capabilities Retina has two major features: diff --git a/docs/01-Introduction/01-intro.md b/docs/01-Introduction/01-intro.md index 5924a9bba8..bdff1241af 100644 --- a/docs/01-Introduction/01-intro.md +++ b/docs/01-Introduction/01-intro.md @@ -94,3 +94,18 @@ Check out our talk from KubeCon 2024 which goes into this topic even further - [ The following are known system requirements for installing Retina: - Minimum Linux Kernel Version: v5.4.0 + +## Known Limitations + +### Performance Considerations for High-Core-Count Systems + +Community users have reported performance considerations when using **Advanced metrics with the `packetparser` plugin** on nodes with high CPU core counts (32+ cores) under sustained, high-volume network load. + +If you plan to deploy Retina in Advanced mode on large node types with network-intensive workloads, consider: + +1. **Start with Basic metrics mode** (does not use `packetparser`) +2. Enable `dataSamplingRate` if you need Advanced metrics +3. Monitor CPU usage and network throughput after deployment +4. See [`packetparser` performance considerations](../03-Metrics/plugins/Linux/packetparser.md#performance-considerations) for more information + +The Retina team is evaluating options to address these reported concerns in future releases. diff --git a/docs/01-Introduction/02-architecture.md b/docs/01-Introduction/02-architecture.md index b125aeb7ca..6169d766e8 100644 --- a/docs/01-Introduction/02-architecture.md +++ b/docs/01-Introduction/02-architecture.md @@ -14,6 +14,8 @@ The plugins have a very specific scope by design, and Retina is designed to be e The plugins are responsible for installing the eBPF programs into the host kernel during startup. These eBPF programs collect metrics from events in the kernel level, which are then passed to the user space where they are parsed and converted into a `flow` data structure. Depending on the Control Plane being used, the data will either be sent to a Retina Enricher, or written to an external channel which is consumed by a Hubble observer - more on this in the [Control Plane](#control-plane) section below. It is not required for a plugin to use eBPF, it can also use syscalls or other API calls. In either case, the plugins will implement the same [interface](https://github.com/microsoft/retina/blob/main/pkg/plugin/registry/registry.go). +**Data Transfer Mechanisms:** eBPF programs transfer data from kernel to user space using specialized data structures. The `packetparser` plugin currently uses **perf arrays** (BPF_MAP_TYPE_PERF_EVENT_ARRAY), which create per-CPU buffers. Community users have reported performance considerations with this approach on high-core-count systems. See [packetparser performance considerations](../03-Metrics/plugins/Linux/packetparser.md#performance-considerations) for details. + Some examlpes of existing Retina plugins: - Drop Reason - measures the number of packets/bytes dropped and the reason and the direction of the drop. diff --git a/docs/03-Metrics/plugins/Linux/packetparser.md b/docs/03-Metrics/plugins/Linux/packetparser.md index d2a6d92618..e2a1621789 100644 --- a/docs/03-Metrics/plugins/Linux/packetparser.md +++ b/docs/03-Metrics/plugins/Linux/packetparser.md @@ -15,6 +15,39 @@ The `packetparser` plugin requires the `CAP_NET_ADMIN` and `CAP_SYS_ADMIN` capab `packetparser` does not produce Basic metrics. In Advanced mode (refer to [Metric Modes](../../modes/modes.md)), the plugin transforms an eBPF result into an enriched `Flow` by adding Pod information based on IP. It then sends the `Flow` to an external channel, enabling *several modules* to generate Pod-Level metrics. +## Performance Considerations + +### Reported Performance Impact on High-Core-Count Systems + +Community users have reported performance considerations when running the `packetparser` plugin on systems with high CPU core counts (32+ cores) under sustained network load. While these reports have not been independently verified by the Retina maintainers, we document them here for awareness. + +**User-Reported Observations:** + +A detailed analysis by a Retina user (see [this blog post](https://blog.zmalik.dev/p/who-will-observe-the-observability)) and [KubeCon 2025 talk](https://www.youtube.com/watch?v=J-Zx64mJzVk) documented performance degradation that scaled non-linearly with CPU core count on nodes running network-intensive, multi-threaded workloads. + +**Current Implementation:** + +The `packetparser` plugin currently uses **BPF_MAP_TYPE_PERF_EVENT_ARRAY** for kernel-to-userspace data transfer. This architecture creates per-CPU buffers that must be polled by a single reader thread. On systems with many CPU cores, this can lead to: + +- Increased context switching overhead +- Memory access patterns that may not scale linearly +- Potential NUMA-related penalties on multi-socket systems + +**Alternative Approaches:** + +Alternative data transfer mechanisms like BPF ring buffers (BPF_MAP_TYPE_RINGBUF, available in Linux kernel 5.8+) use a shared buffer architecture that may perform better on high-core-count systems. However, **Retina does not currently support ring buffers for packetparser**. Future versions may provide configurable data transfer mechanisms. + +#### If You Experience Performance Issues + +If you observe performance degradation on high-core-count nodes: + +1. **Disable `packetparser`**: Use Basic metrics mode which doesn't require this plugin +2. **Enable Sampling**: Use the `dataSamplingRate` configuration option (see [Sampling](#sampling) section) +3. **Use High Data Aggregation**: Configure `high` [data aggregation](../../../05-Concepts/data-aggregation.md) +4. **Monitor Impact**: Watch for elevated CPU usage, context switches, or throughput changes + +**Note:** The Retina team is evaluating options for addressing reported performance concerns, including potential support for alternative data transfer mechanisms. Community feedback and contributions are welcome. + ## Sampling Since `packetparser` produces many enriched `Flow` objects it can be quite expensive for user space to process. Thus, when operating in `high` [data aggregation](../../../05-Concepts/data-aggregation.md) level optional sampling for reported packets is available via the `dataSamplingRate` configuration option. diff --git a/docs/06-Troubleshooting/performance.md b/docs/06-Troubleshooting/performance.md new file mode 100644 index 0000000000..74e247423d --- /dev/null +++ b/docs/06-Troubleshooting/performance.md @@ -0,0 +1,176 @@ +# Performance Troubleshooting + +This guide helps diagnose and address potential performance issues when running Retina, particularly the `packetparser` plugin on high-core-count systems. + +## Background + +Community users have reported performance considerations when running the `packetparser` plugin (used in Advanced metrics mode) on systems with high CPU core counts under sustained network load. For detailed background, see the [`packetparser` performance considerations](../03-Metrics/plugins/Linux/packetparser.md#performance-considerations). + +## Symptoms to Monitor + +Watch for these indicators after deploying Retina: + +- **Decreased network throughput** compared to baseline +- **High CPU usage** by Retina agent pods +- **Elevated context switches** on nodes running Retina +- **Increased latency** in network-intensive applications + +## Diagnostic Steps + +### Step 1: Identify Your Configuration + +Check which plugins are enabled: + +```bash +kubectl get configmap retina-config -n kube-system -o yaml | grep enabledPlugin +``` + +If `packetparser` is enabled, you're running Advanced metrics mode which is more resource-intensive. + +### Step 2: Check Node Specifications + +```bash +# Check core count on nodes +kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.capacity.cpu + +# Identify nodes with high core counts (32+) +kubectl get nodes -o json | jq '.items[] | select((.status.capacity.cpu | tonumber) >= 32) | {name: .metadata.name, cpu: .status.capacity.cpu}' +``` + +### Step 3: Monitor Retina Resource Usage + +```bash +# Check CPU and memory usage of Retina pods +kubectl top pods -n kube-system -l app=retina + +# For more detailed analysis, check specific pod on a node +RETINA_POD=$(kubectl get pods -n kube-system -l app=retina -o jsonpath='{.items[0].metadata.name}') +kubectl top pod $RETINA_POD -n kube-system +``` + +### Step 4: Establish Performance Baseline + +Before and after Retina deployment, measure: + +- Network throughput (using your application's metrics or tools like iperf3) +- Application response times +- CPU utilization on nodes + +## Mitigation Options + +If you observe performance impact, consider these approaches: + +### Option 1: Use Basic Metrics Mode (Recommended) + +Basic metrics mode provides node-level observability without the `packetparser` plugin: + +```bash +# Reinstall or upgrade Retina without packetparser +helm upgrade retina oci://ghcr.io/microsoft/retina/charts/retina \ + --set enabledPlugin_linux="\[dropreason\,packetforward\,linuxutil\,dns\]" \ + --reuse-values +``` + +**Trade-off:** You'll have node-level metrics only, not pod-level metrics. + +### Option 2: Enable Data Sampling + +Reduce event volume by sampling packets: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: retina-config + namespace: kube-system +data: + config.yaml: | + dataSamplingRate: 10 # Sample 1 out of every 10 packets +``` + +**Trade-off:** Reduced data granularity, but lower overhead. + +### Option 3: Use High Data Aggregation Level + +Reduce events at the eBPF level: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: retina-config + namespace: kube-system +data: + config.yaml: | + dataAggregationLevel: "high" +``` + +**Trade-off:** Disables host interface monitoring; API server latency metrics may be less reliable. + +### Option 4: Selective Deployment + +Deploy Retina only on nodes where you need detailed observability: + +```yaml +# Use node selectors or taints/tolerations +apiVersion: apps/v1 +kind: DaemonSet +spec: + template: + spec: + nodeSelector: + retina-enabled: "true" +``` + +## Advanced Diagnostics + +### Inspecting eBPF Maps + +To see what data structures Retina is using: + +```bash +# Access the node +kubectl debug node/ -it --image=ubuntu + +# In the debug container, enter the host namespace +chroot /host + +# List BPF maps (requires bpftool) +bpftool map list | grep retina + +# Check the packetparser map type +bpftool map show name retina_packetparser_events +``` + +Currently, `packetparser` uses `BPF_MAP_TYPE_PERF_EVENT_ARRAY`. + +### Monitoring Event Rates (Advanced) + +If you have bpftrace available on nodes: + +```bash +# Monitor perf_event activity +sudo bpftrace -e ' + kprobe:perf_event_output { @events = count(); } + interval:s:5 { print(@events); clear(@events); } +' +``` + +High event rates may correlate with increased CPU usage. + +## Reporting Issues + +If you experience performance issues, please report them with: + +1. **Node specifications**: CPU count, memory, kernel version +2. **Retina configuration**: Version, enabled plugins, configuration settings +3. **Workload characteristics**: Network throughput, number of pods, traffic patterns +4. **Performance metrics**: CPU usage, network throughput before/after, specific observations + +Open an issue at: + +## Further Resources + +- [Packetparser Performance Considerations](../03-Metrics/plugins/Linux/packetparser.md#performance-considerations) +- [Data Aggregation Levels](../05-Concepts/data-aggregation.md) +- [Configuration Options](../02-Installation/03-Config.md) diff --git a/site/package-lock.json b/site/package-lock.json index eab30316e1..4ccd8d0815 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -239,7 +239,6 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.0.tgz", "integrity": "sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/client-common": "5.40.0", "@algolia/requester-browser-xhr": "5.40.0", @@ -365,7 +364,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2157,7 +2155,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2180,7 +2177,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2290,7 +2286,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2712,7 +2707,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3664,7 +3658,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.9.1", "@docusaurus/logger": "3.9.1", @@ -4775,7 +4768,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.0.tgz", "integrity": "sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5090,7 +5082,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5464,7 +5455,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.7.tgz", "integrity": "sha512-KUnDCJF5+AiZd8owLIeVHqmW9yM4sqmDVf2JRJiBMFkGvkoZ4/WyV2lL4zVsoinmRS/W3FeEdZLEWFRofnT2FQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5801,7 +5791,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5874,7 +5863,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5920,7 +5908,6 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.0.tgz", "integrity": "sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/abtesting": "1.6.0", "@algolia/client-abtesting": "5.40.0", @@ -6502,7 +6489,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -7521,7 +7507,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9069,7 +9054,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13781,7 +13765,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14297,7 +14280,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15171,7 +15153,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -16001,7 +15982,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16013,7 +15993,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -16066,7 +16045,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -16093,7 +16071,6 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17238,7 +17215,6 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, - "peer": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -17982,7 +17958,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18243,8 +18218,7 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "peer": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18315,7 +18289,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "devOptional": true, - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18678,7 +18651,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18882,7 +18854,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -19152,7 +19123,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -19540,7 +19510,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From 47de328cc04f4e8c9f6ed0d529f8a84880f11fc5 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:41:24 +0000 Subject: [PATCH 175/448] fix: Cleanup for windows release-images (#1968) # Description Cleanup before building windows images. Check this PR for more info https://github.com/microsoft/retina/pull/1950 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/workflows/release-images.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index ec865daefb..14d4536cfa 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -85,6 +85,14 @@ jobs: - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + + - run: df -h + - name: "node-cleanup" + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL + sudo docker image prune --all --force + sudo docker builder prune -a + - run: df -h - name: Build/Push Images shell: bash From fe63cdd188961c49021d9e8e775d8e121f3402ef Mon Sep 17 00:00:00 2001 From: Mereta Date: Mon, 8 Dec 2025 17:59:32 +0000 Subject: [PATCH 176/448] fix(revert-1952): fix: add validation of error to k8sWatcherErrorHandler (#1969) Reverts microsoft/retina#1952 --- pkg/k8s/watcher_linux.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/k8s/watcher_linux.go b/pkg/k8s/watcher_linux.go index be1081a5b8..e1a119b03c 100644 --- a/pkg/k8s/watcher_linux.go +++ b/pkg/k8s/watcher_linux.go @@ -43,12 +43,7 @@ func Start(ctx context.Context, k *watchers.K8sWatcher) { // retinaK8sErrorHandler is a custom error handler for the watcher // that logs the error and tags the error to easily identify func k8sWatcherErrorHandler(c context.Context, e error, s string, i ...interface{}) { - if e == nil { - return - } - errStr := e.Error() - logError := func(er, r string) { logger.WithFields(logrus.Fields{ "underlyingError": er, From 3fd973d9f1174211e864373cb7524fab455e1d74 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Tue, 9 Dec 2025 15:40:36 +0000 Subject: [PATCH 177/448] deps: Updating hubble to mitigate cve (#1973) # Description Please provide a brief description of the changes made in this pull request. ## Related Issue This pull request updates the default version of Hubble used in the build process. The change ensures that future builds will use the newer `v1.18.3` version of Hubble instead of `v1.17.5`. * Build configuration update: * Updated the `HUBBLE_VERSION` variable in the `Makefile` to use `v1.18.3` as the default Hubble version. If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image Hubble is currently using 1.25.3 go version, we cannot fix this cve from our side, I have highlight it in hubble slack channel. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. From e8f56399998d98cd82f2bbb6d7f2c9dfe452c65b Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 9 Dec 2025 11:22:48 -0500 Subject: [PATCH 178/448] fix: stop endpoint manager in the agent to regen endpoints periodically (#1970) # Description Disabling the Endpoint regeneration from the Agent endpoint manager by setting the regen interval to 0. Verified that retina pods are healthy and no regenerating endpoint logs in test cluster. ## Related Issue Close #1514 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- cmd/hubble/daemon_main_linux.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/hubble/daemon_main_linux.go b/cmd/hubble/daemon_main_linux.go index c4a609e3b5..e88c195882 100644 --- a/cmd/hubble/daemon_main_linux.go +++ b/cmd/hubble/daemon_main_linux.go @@ -60,6 +60,9 @@ func InitGlobalFlags(cmd *cobra.Command, vp *viper.Viper) { flags.String(option.ConfigDir, "/retina/config", `Configuration directory that contains a file for each option`) option.BindEnv(vp, option.ConfigDir) + // Set the default value for the endpoint GC interval to 0, which disables it. + vp.Set(option.EndpointGCInterval, 0) + if err := vp.BindPFlags(flags); err != nil { logger.Fatalf("BindPFlags failed: %s", err) } From ba289ddf229288e15c62af7d9872d07887b962fc Mon Sep 17 00:00:00 2001 From: Mereta Date: Tue, 9 Dec 2025 17:23:37 +0000 Subject: [PATCH 179/448] fix(cve): Hubble release version (#1974) # Description Updating Hubble release version. Related PR's: https://github.com/microsoft/retina/pull/1973 https://github.com/microsoft/retina/pull/1920 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: mereta --- controller/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 1558af560d..3a9b0147d1 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -98,7 +98,7 @@ RUN arr="clang tcpdump ip ss iptables-legacy iptables-legacy-save iptables-nft i ARG GOARCH=amd64 ENV HUBBLE_ARCH=${GOARCH} # ARG HUBBLE_VERSION may be modified via the update-hubble GitHub Action -ARG HUBBLE_VERSION=v1.17.5 +ARG HUBBLE_VERSION=v1.18.3 ENV HUBBLE_VERSION=${HUBBLE_VERSION} RUN echo "Hubble version: $HUBBLE_VERSION" && \ wget --no-check-certificate https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz && \ From e938751e953bc165acdef4f5c9022f6152859739 Mon Sep 17 00:00:00 2001 From: Isaiah Raya Date: Tue, 9 Dec 2025 10:45:09 -0800 Subject: [PATCH 180/448] deps(cve): Upgrade Windows to Latest Base Version to Resolve CVEs (#1975) # Description Resolves Windows CVEs in the base images by upgrading to the latest Windows images. Updates Windows nanoserver Image to - `mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca` for 2019 - `mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5` for 2022 Updates Windows servercore Image to - `mcr.microsoft.com/windows/nanoserver@sha256:244f1c6f590ca5a417c241a11cd6719a456f9771c45a0c2b195d5636763a7f0e` for 2019 - `mcr.microsoft.com/windows/nanoserver@sha256:643adf84ee2338ee4811fd891adb9e912917dc6c0ca85399982e1bebda4f2295` for 2022 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- controller/Dockerfile | 4 ++-- controller/Dockerfile.windows-2019 | 2 +- controller/Dockerfile.windows-2022 | 2 +- controller/Dockerfile.windows-native | 2 +- controller/Dockerfile.windows-retina-oss-build | 4 ++-- operator/Dockerfile.windows-2019 | 2 +- operator/Dockerfile.windows-2022 | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 3a9b0147d1..ddca538728 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -12,10 +12,10 @@ FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599a FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS azurelinux-distroless # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9 AS ltsc2019 +FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca AS ltsc2019 # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 # build stages diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index a214f85bf9..19fb14ed3a 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -17,7 +17,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/ca # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9 as final +FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index f5bcb94744..a797e47338 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/co RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2 as final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 as final COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY --from=builder /usr/bin/controller.exe controller.exe diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index a08c0966ea..f1794dfbe0 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:580b7fa4040be7b47d79c25fb73e3d6da2e68f32b95d9d4dfb70bde33564fc4a AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:643adf84ee2338ee4811fd891adb9e912917dc6c0ca85399982e1bebda4f2295 AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index 73348bfede..72249d4fde 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -3,10 +3,10 @@ ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:dfd0f4a06d08d7cad271efcfac0d05ca9dc5fa7c55df15b0d8491c81105974a9 AS ltsc2019 +FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca AS ltsc2019 # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:92659de869382c14a0276a5e93215d88cb182dc22f1ff3ada1f1b68b8648f3b2 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 index 5c1e679364..0fbae1b92e 100644 --- a/operator/Dockerfile.windows-2019 +++ b/operator/Dockerfile.windows-2019 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:ea1b43fa8972684a5a284a6f441f91991fa7545d6912d2aecbf6c5ba60e73155 +FROM mcr.microsoft.com/windows/nanoserver@sha256:244f1c6f590ca5a417c241a11cd6719a456f9771c45a0c2b195d5636763a7f0e COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 6f90bed698..a4b3113006 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:580b7fa4040be7b47d79c25fb73e3d6da2e68f32b95d9d4dfb70bde33564fc4a +FROM mcr.microsoft.com/windows/nanoserver@sha256:643adf84ee2338ee4811fd891adb9e912917dc6c0ca85399982e1bebda4f2295 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 From 6447b7ea24687c8188c27a93555d94c3df43fa04 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 10 Dec 2025 09:57:00 +0000 Subject: [PATCH 181/448] fix: add logging to K8sErrorHandler when error is nil (#1972) # Description Add logging to K8sErrorHandler when error is nil closes #1951 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- pkg/k8s/watcher_linux.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/k8s/watcher_linux.go b/pkg/k8s/watcher_linux.go index e1a119b03c..14df5a0982 100644 --- a/pkg/k8s/watcher_linux.go +++ b/pkg/k8s/watcher_linux.go @@ -43,7 +43,15 @@ func Start(ctx context.Context, k *watchers.K8sWatcher) { // retinaK8sErrorHandler is a custom error handler for the watcher // that logs the error and tags the error to easily identify func k8sWatcherErrorHandler(c context.Context, e error, s string, i ...interface{}) { + if e == nil { + // TODO: handle key/values pairs in a better way + // current example output: time="2009-11-10T23:00:00Z" level=error msg="msg: Some error message -- key/values: [int 1 str world]" + logger.WithContext(c).Errorf("msg: %s -- key/values: %+v", s, i) + return + } + errStr := e.Error() + logError := func(er, r string) { logger.WithFields(logrus.Fields{ "underlyingError": er, From 6385c4082e0bfed3a8c3f86efea41f539efa4f1f Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:17:01 +0000 Subject: [PATCH 182/448] fix(tests): Fix packetparser tests (#1977) # Description This PR fixes unit test failures in the `packetparser` plugin: - Mocks `metrics.ParsedPacketsCounter` in `TestReadDataPodLevelEnabled` to prevent a nil pointer dereference during test execution. - Updates the expected dynamic header content in `TestPacketParseGenerate` to match the actual generated output, which now includes `DATA_SAMPLING_RATE` and `BYPASS_LOOKUP_IP_OF_INTEREST` definitions. ## Related PRs This test was broken in the following PRs - #624 - #1767 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image ## Additional Notes We have a bigger issue which is CI is not showing a failure when single test fails, we will look into that and create another PR to fix that. See this example (FAIL not caught) - reference #1688 https://github.com/microsoft/retina/actions/runs/20115412850/job/57723528708#step:4:3145 --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/plugin/packetparser/packetparser_linux_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go index 50903852a1..0d32b8fcf6 100644 --- a/pkg/plugin/packetparser/packetparser_linux_test.go +++ b/pkg/plugin/packetparser/packetparser_linux_test.go @@ -344,6 +344,10 @@ func TestReadDataPodLevelEnabled(t *testing.T) { metrics.LostEventsCounter = mICounterVec + mParsedPacketsCounter := metrics.NewMockCounterVec(ctrl) + mParsedPacketsCounter.EXPECT().WithLabelValues(gomock.Any()).Return(prometheus.NewCounter(prometheus.CounterOpts{})).AnyTimes() + metrics.ParsedPacketsCounter = mParsedPacketsCounter + exCh := make(chan *v1.Event, 10) p.SetupChannel(exCh) @@ -560,22 +564,22 @@ func TestPacketParseGenerate(t *testing.T) { { name: "PodLevelEnabled", cfg: cfgPodLevelEnabled, - expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n", + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n#define DATA_SAMPLING_RATE 0\n", }, { name: "ConntrackMetricsEnabled", cfg: cfgConntrackMetricsEnabled, - expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define ENABLE_CONNTRACK_METRICS 1\n#define DATA_AGGREGATION_LEVEL 1\n", + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define ENABLE_CONNTRACK_METRICS 1\n#define DATA_AGGREGATION_LEVEL 1\n#define DATA_SAMPLING_RATE 0\n", }, { name: "DataAggregationLevelLow", cfg: cfgDataAggregationLevelLow, - expectedContents: "#define DATA_AGGREGATION_LEVEL 0\n", + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n#define DATA_AGGREGATION_LEVEL 0\n#define DATA_SAMPLING_RATE 0\n", }, { name: "DataAggregationLevelHigh", cfg: cfgDataAggregationLevelHigh, - expectedContents: "#define DATA_AGGREGATION_LEVEL 1\n", + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n#define DATA_AGGREGATION_LEVEL 1\n#define DATA_SAMPLING_RATE 0\n", }, } From 8f39ea2e4c66cbc85be24831d406233f73c921ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:54:47 -0500 Subject: [PATCH 183/448] deps: bump actions/upload-artifact from 5.0.0 to 6.0.0 (#1982) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0.
Release notes

Sourced from actions/upload-artifact's releases.

v6.0.0

v6 - What's new

[!IMPORTANT] actions/upload-artifact@v6 now runs on Node.js 24 (runs.using: node24) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.

Node.js 24

This release updates the runtime to Node.js 24. v5 had preliminary support for Node.js 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.

What's Changed

Full Changelog: https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0

Commits
  • b7c566a Merge pull request #745 from actions/upload-artifact-v6-release
  • e516bc8 docs: correct description of Node.js 24 support in README
  • ddc45ed docs: update README to correct action name for Node.js 24 support
  • 615b319 chore: release v6.0.0 for Node.js 24 support
  • 017748b Merge pull request #744 from actions/fix-storage-blob
  • 38d4c79 chore: rebuild dist
  • 7d27270 chore: add missing license cache files for @​actions/core, @​actions/io, and mi...
  • 5f643d3 chore: update license files for @​actions/artifact@​5.0.1 dependencies
  • 1df1684 chore: update package-lock.json with @​actions/artifact@​5.0.1
  • b5b1a91 fix: update @​actions/artifact to ^5.0.0 for Node.js 24 punycode fix
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=5.0.0&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e70edf6eac..f8d1e1d57a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -36,7 +36,7 @@ jobs: make test-image IMAGE_NAMESPACE=${{ github.repository }} PLATFORM=linux/amd64 - name: Upload Artifacts - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: coverage-files path: ./artifacts/coverage* From e4f36e16970bdd8508fab4d80028020d2f19d370 Mon Sep 17 00:00:00 2001 From: Mereta Date: Wed, 17 Dec 2025 15:29:55 +0000 Subject: [PATCH 184/448] feat(hubble-test): Add Hubble E2E test scenarios (#1962) # Description Adding multi-arch Hubble CP test scenarios. ## Related Issue #1056 If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed All Tests pass locally. On ran on AMD64 node. Excluded: job.AddScenario(windows.ValidateWindowsBasicMetric()) image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: mereta --- Makefile | 3 + test/e2e/common/common.go | 4 +- test/e2e/common/validate-metric.go | 52 +++++ .../azure/create-cluster-with-npm.go | 13 +- test/e2e/framework/constants/common.go | 15 ++ test/e2e/framework/constants/hubble.go | 31 +++ test/e2e/framework/constants/retina.go | 17 ++ .../kubernetes/create-agnhost-statefulset.go | 17 +- .../kubernetes/create-network-policy.go | 8 +- .../kubernetes/install-hubble-helm.go | 8 +- test/e2e/framework/prometheus/prometheus.go | 48 ++++- test/e2e/jobs/jobs.go | 30 ++- test/e2e/retina_e2e_test.go | 13 +- test/e2e/scenarios/dns/scenarios.go | 10 +- .../dns/validate-advanced-dns-metric.go | 6 +- .../dns/validate-basic-dns-metric.go | 6 +- test/e2e/scenarios/hubble/dns/labels.go | 26 +++ test/e2e/scenarios/hubble/dns/scenario.go | 93 +++++++++ test/e2e/scenarios/hubble/drop/labels.go | 27 +++ test/e2e/scenarios/hubble/drop/scenario.go | 138 +++++++++++++ .../e2e/scenarios/hubble/flow/pod2podInter.go | 184 ++++++++++++++++++ .../e2e/scenarios/hubble/flow/pod2podIntra.go | 129 ++++++++++++ test/e2e/scenarios/hubble/flow/pod2world.go | 104 ++++++++++ test/e2e/scenarios/hubble/flow/types.go | 57 ++++++ .../hubble/service}/scenario.go | 0 test/e2e/scenarios/hubble/tcp/labels.go | 27 +++ test/e2e/scenarios/hubble/tcp/scenario.go | 95 +++++++++ .../latency/validate-latency-metric.go | 4 +- .../scenarios/windows/validate-hns-metrics.go | 4 +- 29 files changed, 1118 insertions(+), 51 deletions(-) create mode 100644 test/e2e/common/validate-metric.go create mode 100644 test/e2e/framework/constants/common.go create mode 100644 test/e2e/framework/constants/hubble.go create mode 100644 test/e2e/framework/constants/retina.go create mode 100644 test/e2e/scenarios/hubble/dns/labels.go create mode 100644 test/e2e/scenarios/hubble/dns/scenario.go create mode 100644 test/e2e/scenarios/hubble/drop/labels.go create mode 100644 test/e2e/scenarios/hubble/drop/scenario.go create mode 100644 test/e2e/scenarios/hubble/flow/pod2podInter.go create mode 100644 test/e2e/scenarios/hubble/flow/pod2podIntra.go create mode 100644 test/e2e/scenarios/hubble/flow/pod2world.go create mode 100644 test/e2e/scenarios/hubble/flow/types.go rename test/e2e/{hubble => scenarios/hubble/service}/scenario.go (100%) create mode 100644 test/e2e/scenarios/hubble/tcp/labels.go create mode 100644 test/e2e/scenarios/hubble/tcp/scenario.go diff --git a/Makefile b/Makefile index 3d18478709..9d8b350e82 100644 --- a/Makefile +++ b/Makefile @@ -601,6 +601,9 @@ simplify-dashboards: run-perf-test: go test -v ./test/e2e/retina_perf_test.go -timeout 2h -tags=perf -count=1 -args -image-tag=${TAG} -image-registry=${IMAGE_REGISTRY} -image-namespace=${IMAGE_NAMESPACE} +run-e2e-test: + go test -v ./test/e2e/ -timeout 1h -tags=e2e -count=1 -args -image-tag=${TAG} -image-registry=${IMAGE_REGISTRY} -image-namespace=${IMAGE_NAMESPACE} + .PHONY: update-hubble update-hubble: @echo "Checking for Hubble updates..." diff --git a/test/e2e/common/common.go b/test/e2e/common/common.go index 19a04172b0..4648ffc2b8 100644 --- a/test/e2e/common/common.go +++ b/test/e2e/common/common.go @@ -17,7 +17,6 @@ import ( ) const ( - RetinaPort int = 10093 // netObsRGtag is used to tag resources created by this test suite NetObsRGtag = "-e2e-netobs-" KubeSystemNamespace = "kube-system" @@ -48,6 +47,9 @@ var ( RetinaChartPath = func(rootDir string) string { return filepath.Join(rootDir, "deploy", "standard", "manifests", "controller", "helm", "retina") } + HubbleChartPath = func(rootDir string) string { + return filepath.Join(rootDir, "deploy", "hubble", "manifests", "controller", "helm", "retina") + } RetinaAdvancedProfilePath = func(rootDir string) string { return filepath.Join(rootDir, "test", "profiles", "advanced", "values.yaml") } diff --git a/test/e2e/common/validate-metric.go b/test/e2e/common/validate-metric.go new file mode 100644 index 0000000000..8eb31b5057 --- /dev/null +++ b/test/e2e/common/validate-metric.go @@ -0,0 +1,52 @@ +//nolint:revive // package name "common" is used across the E2E test suite +package common + +import ( + "errors" + "fmt" + "log" + + prom "github.com/microsoft/retina/test/e2e/framework/prometheus" +) + +var ErrMetricFound = errors.New("unexpected metric found") + +type ValidateMetric struct { + ForwardedPort string + MetricName string + ValidMetrics []map[string]string + ExpectMetric bool + PartialMatch bool // If true, only the specified labels need to match (metric can have additional labels) +} + +func (v *ValidateMetric) Run() error { + promAddress := fmt.Sprintf("http://localhost:%s/metrics", v.ForwardedPort) + + for _, validMetric := range v.ValidMetrics { + err := prom.CheckMetric(promAddress, v.MetricName, validMetric, v.PartialMatch) + if err != nil { + // If we expect the metric not to be found, return nil if it's not found. + if !v.ExpectMetric && errors.Is(err, prom.ErrNoMetricFound) { + log.Printf("metric %s not found, as expected\n", v.MetricName) + return nil + } + return fmt.Errorf("failed to verify prometheus metrics: %w", err) + } + + // if we expect the metric not to be found, return an error if it is found + if !v.ExpectMetric { + return fmt.Errorf("did not expect to find metric %s matching %+v: %w", v.MetricName, validMetric, ErrMetricFound) + } + + log.Printf("found metric %s matching %+v\n", v.MetricName, validMetric) + } + return nil +} + +func (v *ValidateMetric) Prevalidate() error { + return nil +} + +func (v *ValidateMetric) Stop() error { + return nil +} diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index 80c4ab88b4..fce22b9a91 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -18,11 +18,12 @@ var ( ) const ( - clusterTimeout = 15 * time.Minute - clusterCreateTicker = 30 * time.Second - pollFrequency = 5 * time.Second - AgentARMSKU = "Standard_D4pls_v5" - AuxilaryNodeCount = 1 + clusterTimeout = 15 * time.Minute + clusterCreateTicker = 30 * time.Second + pollFrequency = 5 * time.Second + AgentARMSKU = "Standard_D4pls_v5" + AuxilaryNodeCount = 1 + AuxilaryARMNodeCount = 2 ) type CreateNPMCluster struct { @@ -87,7 +88,7 @@ func (c *CreateNPMCluster) Run() error { npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ //nolint:all Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), // AvailabilityZones: []*string{to.Ptr("1")}, - Count: to.Ptr[int32](AuxilaryNodeCount), + Count: to.Ptr[int32](AuxilaryARMNodeCount), EnableNodePublicIP: to.Ptr(false), Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), OSType: to.Ptr(armcontainerservice.OSTypeLinux), diff --git a/test/e2e/framework/constants/common.go b/test/e2e/framework/constants/common.go new file mode 100644 index 0000000000..d55571bf89 --- /dev/null +++ b/test/e2e/framework/constants/common.go @@ -0,0 +1,15 @@ +package constants + +const ( + MetricsEndpoint = "metrics" + + TCP = "TCP" + UDP = "UDP" + IPV4 = "IPv4" + IPTableRuleDrop = "IPTABLE_RULE_DROP" + SYN = "SYN" + SYNACK = "SYN-ACK" + ACK = "ACK" + FIN = "FIN" + RST = "RST" +) diff --git a/test/e2e/framework/constants/hubble.go b/test/e2e/framework/constants/hubble.go new file mode 100644 index 0000000000..0efb06b151 --- /dev/null +++ b/test/e2e/framework/constants/hubble.go @@ -0,0 +1,31 @@ +package constants + +const ( + // Metrics Port + HubbleMetricsPort = "9965" + + // MetricsName + HubbleDNSQueryMetricName = "hubble_dns_queries_total" + HubbleDNSResponseMetricName = "hubble_dns_responses_total" + HubbleFlowMetricName = "hubble_flows_processed_total" + HubbleDropMetricName = "hubble_drop_total" + HubbleTCPFlagsMetricName = "hubble_tcp_flags_total" + + // Labels + HubbleDestinationLabel = "destination" + HubbleSourceLabel = "source" + HubbleIPsRetunedLabel = "ips_returned" + HubbleQTypesLabel = "qtypes" + HubbleRCodeLabel = "rcode" + HubbleQueryLabel = "query" + + HubbleProtocolLabel = "protocol" + HubbleReasonLabel = "reason" + + HubbleSubtypeLabel = "subtype" + HubbleTypeLabel = "type" + HubbleVerdictLabel = "verdict" + + HubbleFamilyLabel = "family" + HubbleFlagLabel = "flag" +) diff --git a/test/e2e/framework/constants/retina.go b/test/e2e/framework/constants/retina.go new file mode 100644 index 0000000000..8d2c901a7d --- /dev/null +++ b/test/e2e/framework/constants/retina.go @@ -0,0 +1,17 @@ +package constants + +const ( + // Metrics Port + RetinaMetricsPort = "10093" + + // MetricsName + RetinaDropMetricName = "networkobservability_drop_count" + RetinaForwardMetricName = "networkobservability_forward_count" + + // Labels + RetinaSourceLabel = "source" + RetinaDestinationLabel = "destination" + RetinaProtocolLabel = "protocol" + RetinaReasonLabel = "reason" + RetinaDirectionLabel = "direction" +) diff --git a/test/e2e/framework/kubernetes/create-agnhost-statefulset.go b/test/e2e/framework/kubernetes/create-agnhost-statefulset.go index f9689d9f1d..022d25b443 100644 --- a/test/e2e/framework/kubernetes/create-agnhost-statefulset.go +++ b/test/e2e/framework/kubernetes/create-agnhost-statefulset.go @@ -18,7 +18,6 @@ var ErrLabelMissingFromPod = fmt.Errorf("label missing from pod") const ( AgnhostHTTPPort = 80 - AgnhostReplicas = 1 AgnhostArchAmd64 = "amd64" AgnhostArchArm64 = "arm64" ) @@ -29,6 +28,7 @@ type CreateAgnhostStatefulSet struct { ScheduleOnSameNode bool KubeConfigFilePath string AgnhostArch string + AgnhostReplicas *int } func (c *CreateAgnhostStatefulSet) Run() error { @@ -50,7 +50,13 @@ func (c *CreateAgnhostStatefulSet) Run() error { c.AgnhostArch = AgnhostArchAmd64 } - agnhostStatefulSet := c.getAgnhostDeployment(c.AgnhostArch) + // set default replicas to 1 + replicas := 1 + if c.AgnhostReplicas != nil { + replicas = *c.AgnhostReplicas + } + + agnhostStatefulSet := c.getAgnhostDeployment(c.AgnhostArch, replicas) err = CreateResource(ctx, agnhostStatefulSet, clientset) if err != nil { @@ -79,8 +85,11 @@ func (c *CreateAgnhostStatefulSet) Stop() error { return nil } -func (c *CreateAgnhostStatefulSet) getAgnhostDeployment(arch string) *appsv1.StatefulSet { - reps := int32(AgnhostReplicas) +func (c *CreateAgnhostStatefulSet) getAgnhostDeployment(arch string, replicas int) *appsv1.StatefulSet { + if replicas < 1 { + replicas = 1 + } + reps := int32(replicas) //nolint:gosec // replicas controlled by test code var affinity *v1.Affinity if c.ScheduleOnSameNode { diff --git a/test/e2e/framework/kubernetes/create-network-policy.go b/test/e2e/framework/kubernetes/create-network-policy.go index 996e232215..0aa974c80e 100644 --- a/test/e2e/framework/kubernetes/create-network-policy.go +++ b/test/e2e/framework/kubernetes/create-network-policy.go @@ -36,8 +36,8 @@ func (c *CreateDenyAllNetworkPolicy) Run() error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - agnhostStatefulSet := getNetworkPolicy(c.NetworkPolicyNamespace, c.DenyAllLabelSelector) - err = CreateResource(ctx, agnhostStatefulSet, clientset) + networkPolicy := getNetworkPolicy(c.NetworkPolicyNamespace, c.DenyAllLabelSelector) + err = CreateResource(ctx, networkPolicy, clientset) if err != nil { return fmt.Errorf("error creating simple deny-all network policy: %w", err) } @@ -96,8 +96,8 @@ func (d *DeleteDenyAllNetworkPolicy) Run() error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - agnhostStatefulSet := getNetworkPolicy(d.NetworkPolicyNamespace, d.DenyAllLabelSelector) - err = DeleteResource(ctx, agnhostStatefulSet, clientset) + networkPolicy := getNetworkPolicy(d.NetworkPolicyNamespace, d.DenyAllLabelSelector) + err = DeleteResource(ctx, networkPolicy, clientset) if err != nil { return fmt.Errorf("error creating simple deny-all network policy: %w", err) } diff --git a/test/e2e/framework/kubernetes/install-hubble-helm.go b/test/e2e/framework/kubernetes/install-hubble-helm.go index 5e225d08e6..4cf7f32351 100644 --- a/test/e2e/framework/kubernetes/install-hubble-helm.go +++ b/test/e2e/framework/kubernetes/install-hubble-helm.go @@ -23,7 +23,7 @@ const ( HubbleRelayApp = "hubble-relay" ) -type ValidateHubbleStep struct { +type InstallHubbleHelmChart struct { Namespace string ReleaseName string KubeConfigFilePath string @@ -31,7 +31,7 @@ type ValidateHubbleStep struct { TagEnv string } -func (v *ValidateHubbleStep) Run() error { +func (v *InstallHubbleHelmChart) Run() error { ctx, cancel := context.WithTimeout(context.Background(), defaultTimeoutSeconds*time.Second) defer cancel() @@ -146,10 +146,10 @@ func (v *ValidateHubbleStep) Run() error { return nil } -func (v *ValidateHubbleStep) Prevalidate() error { +func (v *InstallHubbleHelmChart) Prevalidate() error { return nil } -func (v *ValidateHubbleStep) Stop() error { +func (v *InstallHubbleHelmChart) Stop() error { return nil } diff --git a/test/e2e/framework/prometheus/prometheus.go b/test/e2e/framework/prometheus/prometheus.go index 3041d776cf..811235547c 100644 --- a/test/e2e/framework/prometheus/prometheus.go +++ b/test/e2e/framework/prometheus/prometheus.go @@ -22,13 +22,16 @@ var ( defaultRetryAttempts = 60 ) -func CheckMetric(promAddress, metricName string, validMetric map[string]string) error { +func CheckMetric(promAddress, metricName string, validMetric map[string]string, partial ...bool) error { defaultRetrier := retry.Retrier{Attempts: defaultRetryAttempts, Delay: defaultRetryDelay} ctx := context.Background() pctx, cancel := context.WithCancel(ctx) defer cancel() + // Default partial to false if not provided + usePartial := len(partial) > 0 && partial[0] + metrics := map[string]*promclient.MetricFamily{} scrapeMetricsFn := func() error { log.Printf("checking for metrics on %s", promAddress) @@ -42,7 +45,11 @@ func CheckMetric(promAddress, metricName string, validMetric map[string]string) // loop through each metric to check for a match, // if none is found then log and return an error which will trigger a retry - err = verifyValidMetricPresent(metricName, metrics, validMetric) + if usePartial { + err = verifyValidMetricPresentPartial(metricName, metrics, validMetric) + } else { + err = verifyValidMetricPresent(metricName, metrics, validMetric) + } if err != nil { log.Printf("failed to find metric matching %s: %+v\n", metricName, validMetric) return ErrNoMetricFound @@ -119,6 +126,43 @@ func getAllPrometheusMetricsFromURL(url string) (map[string]*promclient.MetricFa return metrics, nil } +// verifyValidMetricPresentPartial checks if a metric exists with labels that contain +// all the key-value pairs in validMetric (partial matching - the metric can have additional labels) +func verifyValidMetricPresentPartial(metricName string, data map[string]*promclient.MetricFamily, validMetric map[string]string) error { + for _, metric := range data { + if metric.GetName() == metricName { + for _, metric := range metric.GetMetric() { + + // get all labels and values on the metric + metricLabels := map[string]string{} + for _, label := range metric.GetLabel() { + metricLabels[label.GetName()] = label.GetValue() + } + + // if valid metric is empty, then we just need to make sure the metric and value is present + if len(validMetric) == 0 && len(metricLabels) > 0 { + return nil + } + + // Check if all key-value pairs in validMetric exist in metricLabels + allMatch := true + for key, value := range validMetric { + if metricLabels[key] != value { + allMatch = false + break + } + } + + if allMatch { + return nil + } + } + } + } + + return fmt.Errorf("failed to find metric matching: %+v: %w", validMetric, ErrNoMetricFound) +} + func getAllPrometheusMetricsFromBuffer(buf []byte) (map[string]*promclient.MetricFamily, error) { var parser expfmt.TextParser reader := strings.NewReader(string(buf)) diff --git a/test/e2e/jobs/jobs.go b/test/e2e/jobs/jobs.go index f62de4aa78..fb820c4faa 100644 --- a/test/e2e/jobs/jobs.go +++ b/test/e2e/jobs/jobs.go @@ -9,10 +9,14 @@ import ( "github.com/microsoft/retina/test/e2e/framework/generic" "github.com/microsoft/retina/test/e2e/framework/kubernetes" "github.com/microsoft/retina/test/e2e/framework/types" - "github.com/microsoft/retina/test/e2e/hubble" "github.com/microsoft/retina/test/e2e/scenarios/capture" "github.com/microsoft/retina/test/e2e/scenarios/dns" "github.com/microsoft/retina/test/e2e/scenarios/drop" + hubble_dns "github.com/microsoft/retina/test/e2e/scenarios/hubble/dns" + hubble_drop "github.com/microsoft/retina/test/e2e/scenarios/hubble/drop" + hubble_flow "github.com/microsoft/retina/test/e2e/scenarios/hubble/flow" + hubble_service "github.com/microsoft/retina/test/e2e/scenarios/hubble/service" + hubble_tcp "github.com/microsoft/retina/test/e2e/scenarios/hubble/tcp" "github.com/microsoft/retina/test/e2e/scenarios/latency" tcp "github.com/microsoft/retina/test/e2e/scenarios/tcp" "github.com/microsoft/retina/test/e2e/scenarios/windows" @@ -273,10 +277,10 @@ func UpgradeAndTestRetinaAdvancedMetrics(kubeConfigFilePath, chartPath, valuesFi return job } -func ValidateHubble(kubeConfigFilePath, chartPath string, testPodNamespace string) *types.Job { +func InstallAndTestHubbleMetrics(kubeConfigFilePath, chartPath string) *types.Job { job := types.NewJob("Validate Hubble") - job.AddStep(&kubernetes.ValidateHubbleStep{ + job.AddStep(&kubernetes.InstallHubbleHelmChart{ Namespace: common.KubeSystemNamespace, ReleaseName: "retina", KubeConfigFilePath: kubeConfigFilePath, @@ -284,9 +288,25 @@ func ValidateHubble(kubeConfigFilePath, chartPath string, testPodNamespace strin TagEnv: generic.DefaultTagEnv, }, nil) - job.AddScenario(hubble.ValidateHubbleRelayService()) + hubbleScenarios := []*types.Scenario{ + hubble_service.ValidateHubbleRelayService(), + hubble_service.ValidateHubbleUIService(kubeConfigFilePath), + } - job.AddScenario(hubble.ValidateHubbleUIService(kubeConfigFilePath)) + for _, arch := range common.Architectures { + hubbleScenarios = append(hubbleScenarios, + hubble_dns.ValidateDNSMetric(arch), + hubble_flow.ValidatePodToPodIntraNodeHubbleFlowMetric(arch), + hubble_flow.ValidatePodToPodInterNodeHubbleFlowMetric(arch), + hubble_flow.ValidatePodToWorldHubbleFlowMetric(arch), + hubble_drop.ValidateDropMetric(arch), + hubble_tcp.ValidateTCPMetric(arch), + ) + } + + for _, scenario := range hubbleScenarios { + job.AddScenario(scenario) + } job.AddStep(&kubernetes.EnsureStableComponent{ PodNamespace: common.KubeSystemNamespace, diff --git a/test/e2e/retina_e2e_test.go b/test/e2e/retina_e2e_test.go index 33f19a72f4..d9e70f270d 100644 --- a/test/e2e/retina_e2e_test.go +++ b/test/e2e/retina_e2e_test.go @@ -26,8 +26,6 @@ func TestE2ERetina(t *testing.T) { // Get to root of the repo by going up two directories rootDir := filepath.Dir(filepath.Dir(cwd)) - hubblechartPath := filepath.Join(rootDir, "deploy", "hubble", "manifests", "controller", "helm", "retina") - err = jobs.LoadGenericFlags().Run() require.NoError(t, err, "failed to load generic flags") @@ -54,14 +52,9 @@ func TestE2ERetina(t *testing.T) { ) advanceMetricsE2E.Run(ctx) - // Install and test Hubble basic metrics - validatehubble := types.NewRunner(t, - jobs.ValidateHubble( - common.KubeConfigFilePath(rootDir), - hubblechartPath, - common.TestPodNamespace), - ) - validatehubble.Run(ctx) + // Install and test Hubble metrics + hubbleMetricsE2E := types.NewRunner(t, jobs.InstallAndTestHubbleMetrics(common.KubeConfigFilePath(rootDir), common.HubbleChartPath(rootDir))) + hubbleMetricsE2E.Run(ctx) // Install Retina basic and test captures captureE2E := types.NewRunner(t, diff --git a/test/e2e/scenarios/dns/scenarios.go b/test/e2e/scenarios/dns/scenarios.go index 4c5c4b9804..4fe2f83f85 100644 --- a/test/e2e/scenarios/dns/scenarios.go +++ b/test/e2e/scenarios/dns/scenarios.go @@ -5,10 +5,10 @@ package dns import ( "fmt" "math/rand" - "strconv" "time" "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" "github.com/microsoft/retina/test/e2e/framework/kubernetes" "github.com/microsoft/retina/test/e2e/framework/types" ) @@ -95,8 +95,8 @@ func ValidateBasicDNSMetrics(scenarioName string, req *RequestValidationParams, Step: &kubernetes.PortForward{ Namespace: common.KubeSystemNamespace, LabelSelector: "k8s-app=retina", - LocalPort: strconv.Itoa(common.RetinaPort), - RemotePort: strconv.Itoa(common.RetinaPort), + LocalPort: constants.RetinaMetricsPort, + RemotePort: constants.RetinaMetricsPort, Endpoint: "metrics", OptionalLabelAffinity: "app=" + agnhostName, // port forward to a pod on a node that also has this pod with this label, assuming same namespace }, @@ -209,8 +209,8 @@ func ValidateAdvancedDNSMetrics(scenarioName string, req *RequestValidationParam Step: &kubernetes.PortForward{ Namespace: common.KubeSystemNamespace, LabelSelector: "k8s-app=retina", - LocalPort: strconv.Itoa(common.RetinaPort), - RemotePort: strconv.Itoa(common.RetinaPort), + LocalPort: constants.RetinaMetricsPort, + RemotePort: constants.RetinaMetricsPort, Endpoint: "metrics", OptionalLabelAffinity: "app=" + agnhostName, // port forward to a pod on a node that also has this pod with this label, assuming same namespace }, diff --git a/test/e2e/scenarios/dns/validate-advanced-dns-metric.go b/test/e2e/scenarios/dns/validate-advanced-dns-metric.go index 1c30e343bc..00badbe8bb 100644 --- a/test/e2e/scenarios/dns/validate-advanced-dns-metric.go +++ b/test/e2e/scenarios/dns/validate-advanced-dns-metric.go @@ -6,7 +6,7 @@ import ( "fmt" "log" - "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" "github.com/microsoft/retina/test/e2e/framework/kubernetes" prom "github.com/microsoft/retina/test/e2e/framework/prometheus" "github.com/pkg/errors" @@ -29,7 +29,7 @@ type ValidateAdvancedDNSRequestMetrics struct { } func (v *ValidateAdvancedDNSRequestMetrics) Run() error { - metricsEndpoint := fmt.Sprintf("http://localhost:%d/metrics", common.RetinaPort) + metricsEndpoint := fmt.Sprintf("http://localhost:%s/metrics", constants.RetinaMetricsPort) // Get Pod IP address podIP, err := kubernetes.GetPodIP(v.KubeConfigFilePath, v.PodNamespace, v.PodName) if err != nil { @@ -78,7 +78,7 @@ type ValidateAdvanceDNSResponseMetrics struct { } func (v *ValidateAdvanceDNSResponseMetrics) Run() error { - metricsEndpoint := fmt.Sprintf("http://localhost:%d/metrics", common.RetinaPort) + metricsEndpoint := fmt.Sprintf("http://localhost:%s/metrics", constants.RetinaMetricsPort) // Get Pod IP address podIP, err := kubernetes.GetPodIP(v.KubeConfigFilePath, v.PodNamespace, v.PodName) if err != nil { diff --git a/test/e2e/scenarios/dns/validate-basic-dns-metric.go b/test/e2e/scenarios/dns/validate-basic-dns-metric.go index efbcd5af2f..91662e1bb5 100644 --- a/test/e2e/scenarios/dns/validate-basic-dns-metric.go +++ b/test/e2e/scenarios/dns/validate-basic-dns-metric.go @@ -6,7 +6,7 @@ import ( "fmt" "log" - "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" prom "github.com/microsoft/retina/test/e2e/framework/prometheus" "github.com/pkg/errors" ) @@ -22,7 +22,7 @@ type validateBasicDNSRequestMetrics struct { } func (v *validateBasicDNSRequestMetrics) Run() error { - metricsEndpoint := fmt.Sprintf("http://localhost:%d/metrics", common.RetinaPort) + metricsEndpoint := fmt.Sprintf("http://localhost:%s/metrics", constants.RetinaMetricsPort) validBasicDNSRequestMetricLabels := map[string]string{} @@ -52,7 +52,7 @@ type validateBasicDNSResponseMetrics struct { } func (v *validateBasicDNSResponseMetrics) Run() error { - metricsEndpoint := fmt.Sprintf("http://localhost:%d/metrics", common.RetinaPort) + metricsEndpoint := fmt.Sprintf("http://localhost:%s/metrics", constants.RetinaMetricsPort) if v.Response == EmptyResponse { v.Response = "" diff --git a/test/e2e/scenarios/hubble/dns/labels.go b/test/e2e/scenarios/hubble/dns/labels.go new file mode 100644 index 0000000000..018dd18c4d --- /dev/null +++ b/test/e2e/scenarios/hubble/dns/labels.go @@ -0,0 +1,26 @@ +package dns + +import ( + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" +) + +var ( + podName = "agnhost-dns-0" + validDNSQueryMetricLabels = map[string]string{ + constants.HubbleDestinationLabel: "", + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podName, + constants.HubbleIPsRetunedLabel: "0", + constants.HubbleQTypesLabel: "A", + constants.HubbleRCodeLabel: "", + constants.HubbleQueryLabel: "one.one.one.one.", + } + validDNSResponseMetricLabels = map[string]string{ + constants.HubbleDestinationLabel: common.TestPodNamespace + "/" + podName, + constants.HubbleSourceLabel: "", + constants.HubbleIPsRetunedLabel: "2", + constants.HubbleQTypesLabel: "A", + constants.HubbleRCodeLabel: "No Error", + constants.HubbleQueryLabel: "one.one.one.one.", + } +) diff --git a/test/e2e/scenarios/hubble/dns/scenario.go b/test/e2e/scenarios/hubble/dns/scenario.go new file mode 100644 index 0000000000..3eac66907d --- /dev/null +++ b/test/e2e/scenarios/hubble/dns/scenario.go @@ -0,0 +1,93 @@ +package dns + +import ( + "time" + + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" + "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/microsoft/retina/test/e2e/framework/types" +) + +const ( + sleepDelay = 5 * time.Second +) + +func ValidateDNSMetric(arch string) *types.Scenario { + name := "DNS Metrics - Arch: " + arch + agnhostName := "agnhost-dns" + podName := agnhostName + "-0" + steps := []*types.StepWrapper{ + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: agnhostName, + AgnhostNamespace: common.TestPodNamespace, + AgnhostArch: arch, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.HubbleMetricsPort, + RemotePort: constants.HubbleMetricsPort, + Namespace: common.KubeSystemNamespace, + Endpoint: "metrics", + OptionalLabelAffinity: "app=" + agnhostName, // port forward hubble metrics to a pod on a node that also has this pod with this label, assuming same namespace + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-dns-port-forward" + arch, + }, + }, + { + Step: &kubernetes.ExecInPod{ + PodName: podName, + PodNamespace: common.TestPodNamespace, + Command: "nslookup -type=a one.one.one.one", + }, + Opts: &types.StepOptions{ + ExpectError: false, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Sleep{ + Duration: sleepDelay, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleDNSQueryMetricName, + ValidMetrics: []map[string]string{validDNSQueryMetricLabels}, + ExpectMetric: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleDNSResponseMetricName, + ValidMetrics: []map[string]string{validDNSResponseMetricLabels}, + ExpectMetric: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-dns-port-forward" + arch, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: agnhostName, + ResourceNamespace: common.TestPodNamespace, + }, + }, + } + return types.NewScenario(name, steps...) +} diff --git a/test/e2e/scenarios/hubble/drop/labels.go b/test/e2e/scenarios/hubble/drop/labels.go new file mode 100644 index 0000000000..2ad1ee7afd --- /dev/null +++ b/test/e2e/scenarios/hubble/drop/labels.go @@ -0,0 +1,27 @@ +package drop + +import ( + "github.com/microsoft/retina/test/e2e/framework/constants" +) + +var ( + podName = "agnhost-drop-0" + agnhostName = "agnhost-drop" + + validRetinaDropMetricLabels = map[string]string{ + constants.RetinaReasonLabel: constants.IPTableRuleDrop, + constants.RetinaDirectionLabel: "unknown", + } + + // Note: When the agnhost pod (with deny-all network policy) tries to curl bing.com, + // it triggers a DNS lookup to CoreDNS. The network policy blocks this egress traffic, + // but Cilium/Hubble records the drop at the destination (CoreDNS) ingress side rather + // than the source (agnhost) egress side. + // 'source:kube-system/agnhost-drop-0' is not recorded in Hubble drop metrics. + // We partially validate this metric. + validHubbleDropMetricLabels = map[string]string{ + constants.HubbleSourceLabel: "", + constants.HubbleProtocolLabel: constants.UDP, + constants.HubbleReasonLabel: "POLICY_DENIED", + } +) diff --git a/test/e2e/scenarios/hubble/drop/scenario.go b/test/e2e/scenarios/hubble/drop/scenario.go new file mode 100644 index 0000000000..8066794af5 --- /dev/null +++ b/test/e2e/scenarios/hubble/drop/scenario.go @@ -0,0 +1,138 @@ +package drop + +import ( + "time" + + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" + "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/microsoft/retina/test/e2e/framework/types" +) + +const ( + sleepDelay = 5 * time.Second +) + +func ValidateDropMetric(arch string) *types.Scenario { + name := "Drop Metrics - Arch: " + arch + steps := []*types.StepWrapper{ + { + Step: &kubernetes.CreateDenyAllNetworkPolicy{ + NetworkPolicyNamespace: common.TestPodNamespace, + DenyAllLabelSelector: "app=" + agnhostName, + }, + }, + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: agnhostName, + AgnhostNamespace: common.TestPodNamespace, + AgnhostArch: arch, + }, + }, + // Need this delay to guarantee that the pods will have bpf program attached + { + Step: &types.Sleep{ + Duration: 30 * time.Second, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.RetinaMetricsPort, + RemotePort: constants.RetinaMetricsPort, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + agnhostName, // port forward to a pod on a node that also has this pod with this label, assuming same namespace + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "retina-drop-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.HubbleMetricsPort, + RemotePort: constants.HubbleMetricsPort, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + agnhostName, // port forward hubble metrics to a pod on a node that also has this pod with this label, assuming same namespace + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-drop-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Sleep{ + Duration: sleepDelay, + }, + }, + { + Step: &kubernetes.ExecInPod{ + PodName: podName, + PodNamespace: common.TestPodNamespace, + Command: "curl -s -m 5 bing.com", + }, + Opts: &types.StepOptions{ + ExpectError: true, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.RetinaMetricsPort, + MetricName: constants.RetinaDropMetricName, + ValidMetrics: []map[string]string{validRetinaDropMetricLabels}, + ExpectMetric: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleDropMetricName, + ValidMetrics: []map[string]string{validHubbleDropMetricLabels}, + ExpectMetric: true, + PartialMatch: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-drop-port-forward" + arch, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "retina-drop-port-forward" + arch, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.NetworkPolicy), + ResourceName: "deny-all", + ResourceNamespace: common.TestPodNamespace, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: agnhostName, + ResourceNamespace: common.TestPodNamespace, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + } + return types.NewScenario(name, steps...) +} diff --git a/test/e2e/scenarios/hubble/flow/pod2podInter.go b/test/e2e/scenarios/hubble/flow/pod2podInter.go new file mode 100644 index 0000000000..4662a14398 --- /dev/null +++ b/test/e2e/scenarios/hubble/flow/pod2podInter.go @@ -0,0 +1,184 @@ +package flow + +import ( + "time" + + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" + "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/microsoft/retina/test/e2e/framework/types" +) + +func ValidatePodToPodInterNodeHubbleFlowMetric(arch string) *types.Scenario { + var ( + podnameSrc = "agnhost-flow-inter-src" + podnameDst = "agnhost-flow-inter-dst" + validHubbleFlowMetricSrcToStackLabel = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podnameSrc + "-0", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-stack", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowMetricSrcToEndpointLabel = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podnameDst + "-0", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-endpoint", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowMetricDstToStackLabel = map[string]string{ + constants.HubbleSourceLabel: "", + constants.HubbleDestinationLabel: common.TestPodNamespace + "/" + podnameSrc + "-0", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-stack", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowMetricDstToEndpointLabel = map[string]string{ + constants.HubbleSourceLabel: "", + constants.HubbleDestinationLabel: common.TestPodNamespace + "/" + podnameDst + "-0", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-endpoint", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowMetricsSrcLabels = []map[string]string{ + validHubbleFlowMetricSrcToStackLabel, + validHubbleFlowMetricSrcToEndpointLabel, + } + validHubbleFlowMetricsDstLabels = []map[string]string{ + validHubbleFlowMetricDstToStackLabel, + validHubbleFlowMetricDstToEndpointLabel, + } + ) + name := "Validate pod to pod inter node Hubble flow metrics - Arch: " + arch + steps := []*types.StepWrapper{ + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: podnameSrc, + AgnhostNamespace: common.TestPodNamespace, + AgnhostArch: arch, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: podnameDst, + AgnhostNamespace: common.TestPodNamespace, + AgnhostArch: arch, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + // Need this delay to guarantee that the pods will have bpf program attached + { + Step: &types.Sleep{ + Duration: 30 * time.Second, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.HubbleMetricsPort, + RemotePort: constants.HubbleMetricsPort, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + podnameSrc, + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-src-flow-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: "9966", + RemotePort: constants.HubbleMetricsPort, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + podnameDst, + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-dst-flow-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &CurlPod{ + SrcPodName: podnameSrc + "-0", + SrcPodNamespace: common.TestPodNamespace, + DstPodName: podnameDst + "-0", + DstPodNamespace: common.TestPodNamespace, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Sleep{ + Duration: sleepDelay, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleFlowMetricName, + ValidMetrics: validHubbleFlowMetricsSrcLabels, + ExpectMetric: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: "9966", + MetricName: constants.HubbleFlowMetricName, + ValidMetrics: validHubbleFlowMetricsDstLabels, + ExpectMetric: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-src-flow-port-forward" + arch, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-dst-flow-port-forward" + arch, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: podnameSrc, + ResourceNamespace: common.TestPodNamespace, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: podnameDst, + ResourceNamespace: common.TestPodNamespace, + }, + }, + } + return types.NewScenario(name, steps...) +} diff --git a/test/e2e/scenarios/hubble/flow/pod2podIntra.go b/test/e2e/scenarios/hubble/flow/pod2podIntra.go new file mode 100644 index 0000000000..10d78e667b --- /dev/null +++ b/test/e2e/scenarios/hubble/flow/pod2podIntra.go @@ -0,0 +1,129 @@ +package flow + +import ( + "time" + + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" + "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/microsoft/retina/test/e2e/framework/types" +) + +func intPtr(i int) *int { + return &i +} + +func ValidatePodToPodIntraNodeHubbleFlowMetric(arch string) *types.Scenario { + var ( + podname = "agnhost-flow-intra" + validPod0HubbleFlowLabelsToStack = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podname + "-0", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-stack", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validPod0HubbleFlowLablesToEndpoint = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podname + "-0", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-endpoint", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validPod1HubbleFlowLabelsToStack = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podname + "-1", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-stack", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validPod1HubbleFlowLabelsToEndpoint = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podname + "-1", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-endpoint", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowMetricsLabels = []map[string]string{ + validPod0HubbleFlowLabelsToStack, + validPod0HubbleFlowLablesToEndpoint, + validPod1HubbleFlowLabelsToStack, + validPod1HubbleFlowLabelsToEndpoint, + } + ) + name := "Validate pod to pod intra node Hubble flow metrics - Arch: " + arch + steps := []*types.StepWrapper{ + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: podname, + AgnhostNamespace: common.TestPodNamespace, + ScheduleOnSameNode: true, + AgnhostReplicas: intPtr(2), + AgnhostArch: arch, + }, + }, + // Need this delay to guarantee that the pods will have bpf program attached + { + Step: &types.Sleep{ + Duration: 30 * time.Second, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.HubbleMetricsPort, + RemotePort: constants.HubbleMetricsPort, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + podname, // port forward to a pod on a node that also has this pod with this label, assuming same namespace + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-flow-intra-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &CurlPod{ + SrcPodName: podname + "-0", + SrcPodNamespace: common.TestPodNamespace, + DstPodName: podname + "-1", + DstPodNamespace: common.TestPodNamespace, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Sleep{ + Duration: sleepDelay, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleFlowMetricName, + ValidMetrics: validHubbleFlowMetricsLabels, + ExpectMetric: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-flow-intra-port-forward" + arch, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: podname, + ResourceNamespace: common.TestPodNamespace, + }, + }, + } + return types.NewScenario(name, steps...) +} diff --git a/test/e2e/scenarios/hubble/flow/pod2world.go b/test/e2e/scenarios/hubble/flow/pod2world.go new file mode 100644 index 0000000000..26e341b050 --- /dev/null +++ b/test/e2e/scenarios/hubble/flow/pod2world.go @@ -0,0 +1,104 @@ +package flow + +import ( + "time" + + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" + "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/microsoft/retina/test/e2e/framework/types" +) + +func ValidatePodToWorldHubbleFlowMetric(arch string) *types.Scenario { + var ( + podName = "agnhost-flow-world" + validHubbleFlowToWorldTCPToStackLabel = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podName + "-0", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.TCP, + constants.HubbleSubtypeLabel: "to-stack", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowToWorldUDPToStackLabel = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podName + "-0", + constants.HubbleDestinationLabel: "", + constants.HubbleProtocolLabel: constants.UDP, + constants.HubbleSubtypeLabel: "to-stack", + constants.HubbleTypeLabel: "Trace", + constants.HubbleVerdictLabel: "FORWARDED", + } + validHubbleFlowMetricsLabels = []map[string]string{ + validHubbleFlowToWorldTCPToStackLabel, + validHubbleFlowToWorldUDPToStackLabel, + } + ) + name := "Validate pod to world Hubble flow metrics - Arch: " + arch + steps := []*types.StepWrapper{ + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: podName, + AgnhostNamespace: common.TestPodNamespace, + AgnhostArch: arch, + }, + }, + // Need this delay to guarantee that the pods will have bpf program attached + { + Step: &types.Sleep{ + Duration: 30 * time.Second, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.HubbleMetricsPort, + RemotePort: constants.HubbleMetricsPort, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + podName, + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-flow-to-world-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.ExecInPod{ + PodName: podName + "-0", + PodNamespace: common.TestPodNamespace, + Command: "curl -s -m 5 bing.com", + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Sleep{ + Duration: sleepDelay, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleFlowMetricName, + ValidMetrics: validHubbleFlowMetricsLabels, + ExpectMetric: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-flow-to-world-port-forward" + arch, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: podName, + ResourceNamespace: common.TestPodNamespace, + }, + }, + } + return types.NewScenario(name, steps...) +} diff --git a/test/e2e/scenarios/hubble/flow/types.go b/test/e2e/scenarios/hubble/flow/types.go new file mode 100644 index 0000000000..9ca8f543c4 --- /dev/null +++ b/test/e2e/scenarios/hubble/flow/types.go @@ -0,0 +1,57 @@ +package flow + +import ( + "context" + "fmt" + "time" + + ossK8s "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/pkg/errors" + kubernetes "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" +) + +const ( + sleepDelay = 5 * time.Second +) + +type CurlPod struct { + SrcPodName string + SrcPodNamespace string + DstPodName string + DstPodNamespace string + KubeConfigFilePath string +} + +func (c *CurlPod) Run() error { + config, err := clientcmd.BuildConfigFromFlags("", c.KubeConfigFilePath) + if err != nil { + return fmt.Errorf("error building kubeconfig: %w", err) + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf("error creating Kubernetes client: %w", err) + } + // Get dst pod IP + dstPodIP, err := ossK8s.GetPodIP(c.KubeConfigFilePath, c.DstPodNamespace, c.DstPodName) + if err != nil { + return errors.Wrap(err, "error getting pod IP") + } + cmd := fmt.Sprintf("curl -s -m 5 %s:80", dstPodIP) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + _, err = ossK8s.ExecPod(ctx, clientset, config, c.SrcPodNamespace, c.SrcPodName, cmd) + if err != nil { + return errors.Wrap(err, "error executing command") + } + return nil +} + +func (c *CurlPod) Prevalidate() error { + return nil +} + +func (c *CurlPod) Stop() error { + return nil +} diff --git a/test/e2e/hubble/scenario.go b/test/e2e/scenarios/hubble/service/scenario.go similarity index 100% rename from test/e2e/hubble/scenario.go rename to test/e2e/scenarios/hubble/service/scenario.go diff --git a/test/e2e/scenarios/hubble/tcp/labels.go b/test/e2e/scenarios/hubble/tcp/labels.go new file mode 100644 index 0000000000..ebf4174663 --- /dev/null +++ b/test/e2e/scenarios/hubble/tcp/labels.go @@ -0,0 +1,27 @@ +package tcp + +import ( + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" +) + +var ( + podName = "agnhost-tcp-0" + validHubbleTCPSYNFlag = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podName, + constants.HubbleDestinationLabel: "", + constants.HubbleFamilyLabel: constants.IPV4, + constants.HubbleFlagLabel: constants.SYN, + } + validHubbleTCPFINFlag = map[string]string{ + constants.HubbleSourceLabel: common.TestPodNamespace + "/" + podName, + constants.HubbleDestinationLabel: "", + constants.HubbleFamilyLabel: constants.IPV4, + constants.HubbleFlagLabel: constants.FIN, + } + + validHubbleTCPMetricsLabels = []map[string]string{ + validHubbleTCPSYNFlag, + validHubbleTCPFINFlag, + } +) diff --git a/test/e2e/scenarios/hubble/tcp/scenario.go b/test/e2e/scenarios/hubble/tcp/scenario.go new file mode 100644 index 0000000000..e268e1a64d --- /dev/null +++ b/test/e2e/scenarios/hubble/tcp/scenario.go @@ -0,0 +1,95 @@ +package tcp + +import ( + "time" + + "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" + "github.com/microsoft/retina/test/e2e/framework/kubernetes" + "github.com/microsoft/retina/test/e2e/framework/types" +) + +const ( + sleepDelay = 5 * time.Second +) + +func ValidateTCPMetric(arch string) *types.Scenario { + name := "TCP Flags Metrics - Arch: " + arch + agnhostName := "agnhost-tcp" + podName := agnhostName + "-0" + steps := []*types.StepWrapper{ + { + Step: &kubernetes.CreateAgnhostStatefulSet{ + AgnhostName: agnhostName, + AgnhostNamespace: common.TestPodNamespace, + AgnhostArch: arch, + }, + }, + // Need this delay to guarantee that the pods will have bpf program attached + { + Step: &types.Sleep{ + Duration: 30 * time.Second, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.PortForward{ + LabelSelector: "k8s-app=retina", + LocalPort: constants.HubbleMetricsPort, + RemotePort: constants.HubbleMetricsPort, + Namespace: common.KubeSystemNamespace, + Endpoint: constants.MetricsEndpoint, + OptionalLabelAffinity: "app=" + agnhostName, // port forward to a pod on a node that also has this pod with this label, assuming same namespace + }, + Opts: &types.StepOptions{ + RunInBackgroundWithID: "hubble-tcp-port-forward" + arch, + SkipSavingParametersToJob: true, + }, + }, + { + Step: &kubernetes.ExecInPod{ + PodName: podName, + PodNamespace: common.TestPodNamespace, + Command: "curl -s -m 5 bing.com", + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Sleep{ + Duration: sleepDelay, + }, + }, + { + Step: &common.ValidateMetric{ + ForwardedPort: constants.HubbleMetricsPort, + MetricName: constants.HubbleTCPFlagsMetricName, + ValidMetrics: validHubbleTCPMetricsLabels, + ExpectMetric: true, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + { + Step: &types.Stop{ + BackgroundID: "hubble-tcp-port-forward" + arch, + }, + }, + { + Step: &kubernetes.DeleteKubernetesResource{ + ResourceType: kubernetes.TypeString(kubernetes.StatefulSet), + ResourceName: agnhostName, + ResourceNamespace: common.TestPodNamespace, + }, + Opts: &types.StepOptions{ + SkipSavingParametersToJob: true, + }, + }, + } + + return types.NewScenario(name, steps...) +} diff --git a/test/e2e/scenarios/latency/validate-latency-metric.go b/test/e2e/scenarios/latency/validate-latency-metric.go index f45a7f237c..270ae95969 100644 --- a/test/e2e/scenarios/latency/validate-latency-metric.go +++ b/test/e2e/scenarios/latency/validate-latency-metric.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" prom "github.com/microsoft/retina/test/e2e/framework/prometheus" "github.com/pkg/errors" ) @@ -18,7 +18,7 @@ func (v *ValidateAPIServerLatencyMetric) Prevalidate() error { } func (v *ValidateAPIServerLatencyMetric) Run() error { - promAddress := fmt.Sprintf("http://localhost:%d/metrics", common.RetinaPort) + promAddress := fmt.Sprintf("http://localhost:%s/metrics", constants.RetinaMetricsPort) metric := map[string]string{} err := prom.CheckMetric(promAddress, latencyBucketMetricName, metric) diff --git a/test/e2e/scenarios/windows/validate-hns-metrics.go b/test/e2e/scenarios/windows/validate-hns-metrics.go index d4bcd0de1a..0cb58cc9fc 100644 --- a/test/e2e/scenarios/windows/validate-hns-metrics.go +++ b/test/e2e/scenarios/windows/validate-hns-metrics.go @@ -7,7 +7,7 @@ import ( "log" "time" - "github.com/microsoft/retina/test/e2e/common" + "github.com/microsoft/retina/test/e2e/framework/constants" k8s "github.com/microsoft/retina/test/e2e/framework/kubernetes" prom "github.com/microsoft/retina/test/e2e/framework/prometheus" "github.com/microsoft/retina/test/retry" @@ -74,7 +74,7 @@ func (v *ValidateHNSMetric) Run() error { // wrap this in a retrier because windows is slow var output []byte err = defaultRetrier.Do(context.TODO(), func() error { - output, err = k8s.ExecPod(context.TODO(), clientset, config, windowsRetinaPod.Namespace, windowsRetinaPod.Name, fmt.Sprintf("curl -s http://localhost:%d/metrics", common.RetinaPort)) + output, err = k8s.ExecPod(context.TODO(), clientset, config, windowsRetinaPod.Namespace, windowsRetinaPod.Name, fmt.Sprintf("curl -s http://localhost:%s/metrics", constants.RetinaMetricsPort)) if err != nil { return fmt.Errorf("error executing command in windows retina pod: %w", err) } From fffdf1c802ce9bcf95e1d241a72f28c3e58e4d8b Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 18 Dec 2025 10:19:44 -0500 Subject: [PATCH 185/448] fix: hubble not showing services and app names on relay and ui (#1754) # Description This PR fixes the issue where service IPs are not being resolved in the Hubble relay's flow logs and app names are not showing up on Hubble UI. This was done by introducing a service cache and a label cache via the service and cilium identity controllers. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- cmd/hubble/cells_linux.go | 13 +- pkg/hubble/common/decoder_linux.go | 30 +- pkg/hubble/parser/layer34/parser_linux.go | 7 +- pkg/hubble/parser/parser_linux.go | 30 +- pkg/hubble/parser/seven/parser_linux.go | 7 +- pkg/hubble/resources/cell_linux.go | 16 + pkg/hubble/resources/ciliumidentity_linux.go | 169 ++++++ .../resources/ciliumidentity_linux_test.go | 549 ++++++++++++++++++ pkg/hubble/resources/service_linux.go | 195 +++++++ pkg/hubble/resources/service_linux_test.go | 516 ++++++++++++++++ 10 files changed, 1485 insertions(+), 47 deletions(-) create mode 100644 pkg/hubble/resources/cell_linux.go create mode 100644 pkg/hubble/resources/ciliumidentity_linux.go create mode 100644 pkg/hubble/resources/ciliumidentity_linux_test.go create mode 100644 pkg/hubble/resources/service_linux.go create mode 100644 pkg/hubble/resources/service_linux_test.go diff --git a/cmd/hubble/cells_linux.go b/cmd/hubble/cells_linux.go index e6777640a1..be67848cb4 100644 --- a/cmd/hubble/cells_linux.go +++ b/cmd/hubble/cells_linux.go @@ -9,9 +9,6 @@ import ( "github.com/cilium/cilium/pkg/gops" hubblecell "github.com/cilium/cilium/pkg/hubble/cell" exportercell "github.com/cilium/cilium/pkg/hubble/exporter/cell" - hubbleParser "github.com/cilium/cilium/pkg/hubble/parser" - "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" k8sClient "github.com/cilium/cilium/pkg/k8s/client" "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" @@ -20,13 +17,13 @@ import ( "github.com/cilium/cilium/pkg/pprof" "github.com/cilium/cilium/pkg/recorder" "github.com/cilium/hive/cell" - "github.com/sirupsen/logrus" "k8s.io/client-go/rest" "github.com/microsoft/retina/internal/buildinfo" "github.com/microsoft/retina/pkg/config" rnode "github.com/microsoft/retina/pkg/controllers/daemon/nodereconciler" "github.com/microsoft/retina/pkg/hubble/parser" + "github.com/microsoft/retina/pkg/hubble/resources" retinak8s "github.com/microsoft/retina/pkg/k8s" "github.com/microsoft/retina/pkg/managers/pluginmanager" "github.com/microsoft/retina/pkg/monitoragent" @@ -97,11 +94,9 @@ var ( recorder.Cell, - cell.Provide( - func(l logrus.FieldLogger, ipc *ipcache.IPCache, sc *k8s.ServiceCacheImpl) hubbleParser.Decoder { - return parser.New(l.WithField("decoder", nil), sc, ipc) - }, - ), + // Provides resources for hubble + resources.Cell, + cell.Provide(parser.New), // Provides the node reconciler as node manager rnode.Cell, diff --git a/pkg/hubble/common/decoder_linux.go b/pkg/hubble/common/decoder_linux.go index c247ad6a5d..267d4758ee 100644 --- a/pkg/hubble/common/decoder_linux.go +++ b/pkg/hubble/common/decoder_linux.go @@ -7,7 +7,6 @@ import ( "github.com/cilium/cilium/api/v1/flow" "github.com/cilium/cilium/pkg/identity" ipc "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" "github.com/cilium/cilium/pkg/labels" ) @@ -18,15 +17,23 @@ type EpDecoder interface { IsEndpointOnLocalHost(ip string) bool } +// LabelCache provides a cache for retrieving security labels associated with Cilium identities. +type LabelCache interface { + // GetLabelsFromSecurityIdentity returns the labels for a given security identity. + GetLabelsFromSecurityIdentity(identity.NumericIdentity) []string +} + type epDecoder struct { localHostIP string ipcache *ipc.IPCache + labelCache LabelCache } -func NewEpDecoder(c *ipc.IPCache) EpDecoder { +func NewEpDecoder(c *ipc.IPCache, lc LabelCache) EpDecoder { return &epDecoder{ localHostIP: os.Getenv("NODE_IP"), ipcache: c, + labelCache: lc, } } @@ -54,7 +61,7 @@ func (e *epDecoder) Decode(ip netip.Addr) *flow.Endpoint { case identity.ReservedIdentityWorld: ep.Labels = labels.LabelWorld.GetModel() default: - // TODO: We do not have an api on the ipcache to get the labels from the ip or identity. + ep.Labels = e.labelCache.GetLabelsFromSecurityIdentity(id.ID) } return ep @@ -69,20 +76,3 @@ func (e *epDecoder) IsEndpointOnLocalHost(string) bool { type SvcDecoder interface { Decode(ip netip.Addr) *flow.Service } - -type svcDecoder struct { - svccache k8s.ServiceCache -} - -func NewSvcDecoder(sc k8s.ServiceCache) SvcDecoder { - return &svcDecoder{ - svccache: sc, - } -} - -func (s *svcDecoder) Decode(netip.Addr) *flow.Service { - svc := &flow.Service{} - // TODO: serviceCache from cilium do not have a way to get the service name - // and namespace from the ip. We need to add this to the serviceCache. - return svc -} diff --git a/pkg/hubble/parser/layer34/parser_linux.go b/pkg/hubble/parser/layer34/parser_linux.go index 4b2798dfcb..74c1b4906a 100644 --- a/pkg/hubble/parser/layer34/parser_linux.go +++ b/pkg/hubble/parser/layer34/parser_linux.go @@ -6,7 +6,6 @@ import ( "github.com/cilium/cilium/api/v1/flow" ipc "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" "github.com/microsoft/retina/pkg/hubble/common" "github.com/microsoft/retina/pkg/utils" @@ -20,11 +19,11 @@ type Parser struct { epd common.EpDecoder } -func New(l *logrus.Entry, svc k8s.ServiceCache, c *ipc.IPCache) *Parser { +func New(l *logrus.Entry, svc common.SvcDecoder, c *ipc.IPCache, labelCache common.LabelCache) *Parser { p := &Parser{ l: l.WithField("subsys", "layer34"), - svd: common.NewSvcDecoder(svc), - epd: common.NewEpDecoder(c), + svd: svc, + epd: common.NewEpDecoder(c, labelCache), } // Log the localHostIP for debugging purposes. return p diff --git a/pkg/hubble/parser/parser_linux.go b/pkg/hubble/parser/parser_linux.go index 3d8cdd098f..2aaa698ea3 100644 --- a/pkg/hubble/parser/parser_linux.go +++ b/pkg/hubble/parser/parser_linux.go @@ -6,10 +6,13 @@ import ( "github.com/cilium/cilium/api/v1/flow" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" observer "github.com/cilium/cilium/pkg/hubble/observer/types" + "github.com/cilium/cilium/pkg/hubble/parser" ipc "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" + "github.com/cilium/hive/cell" + "github.com/microsoft/retina/pkg/hubble/common" "github.com/microsoft/retina/pkg/hubble/parser/layer34" "github.com/microsoft/retina/pkg/hubble/parser/seven" + "github.com/sirupsen/logrus" "go.uber.org/zap" "google.golang.org/protobuf/types/known/timestamppb" @@ -22,23 +25,30 @@ var ( errUnknownPayload = errors.New("unknown payload") ) +type Params struct { + cell.In + + Logger logrus.FieldLogger + ServiceReconciler common.SvcDecoder + LabelCache common.LabelCache + + IPCache *ipc.IPCache +} + type Parser struct { - l logrus.FieldLogger - ipcache *ipc.IPCache - svc k8s.ServiceCache + l *logrus.Entry l34 *layer34.Parser l7 *seven.Parser } -func New(l *logrus.Entry, svc k8s.ServiceCache, c *ipc.IPCache) *Parser { +func New(params Params) parser.Decoder { + logger := params.Logger.WithField("subsys", "payloadparser") return &Parser{ - l: l, - ipcache: c, - svc: svc, + l: logger, - l34: layer34.New(l, svc, c), - l7: seven.New(l, svc, c), + l34: layer34.New(logger, params.ServiceReconciler, params.IPCache, params.LabelCache), + l7: seven.New(logger, params.ServiceReconciler, params.IPCache, params.LabelCache), } } diff --git a/pkg/hubble/parser/seven/parser_linux.go b/pkg/hubble/parser/seven/parser_linux.go index 03a2e4ade2..0fb7cb4e18 100644 --- a/pkg/hubble/parser/seven/parser_linux.go +++ b/pkg/hubble/parser/seven/parser_linux.go @@ -7,7 +7,6 @@ import ( "github.com/cilium/cilium/api/v1/flow" ipc "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" "github.com/google/gopacket/layers" "github.com/microsoft/retina/pkg/hubble/common" "github.com/sirupsen/logrus" @@ -20,11 +19,11 @@ type Parser struct { epd common.EpDecoder } -func New(l *logrus.Entry, svc k8s.ServiceCache, c *ipc.IPCache) *Parser { +func New(l *logrus.Entry, svc common.SvcDecoder, c *ipc.IPCache, labelCache common.LabelCache) *Parser { return &Parser{ l: l.WithField("subsys", "seven"), - svd: common.NewSvcDecoder(svc), - epd: common.NewEpDecoder(c), + svd: svc, + epd: common.NewEpDecoder(c, labelCache), } } diff --git a/pkg/hubble/resources/cell_linux.go b/pkg/hubble/resources/cell_linux.go new file mode 100644 index 0000000000..32e9435931 --- /dev/null +++ b/pkg/hubble/resources/cell_linux.go @@ -0,0 +1,16 @@ +package resources + +import ( + "github.com/cilium/cilium/pkg/k8s" + "github.com/cilium/hive/cell" +) + +var Cell = cell.Module( + "resources", + "Resources for Hubble", + cell.Provide(NewServiceHandler), + cell.Provide( + k8s.CiliumIdentityResource, + NewCiliumIdentityHandler, + ), +) diff --git a/pkg/hubble/resources/ciliumidentity_linux.go b/pkg/hubble/resources/ciliumidentity_linux.go new file mode 100644 index 0000000000..b75764452d --- /dev/null +++ b/pkg/hubble/resources/ciliumidentity_linux.go @@ -0,0 +1,169 @@ +package resources + +import ( + "context" + "sync" + + cid "github.com/cilium/cilium/pkg/identity" + cilium_api_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" + "github.com/cilium/cilium/pkg/k8s/resource" + "github.com/cilium/hive/cell" + "github.com/microsoft/retina/pkg/hubble/common" + "github.com/microsoft/retina/pkg/log" + "github.com/pkg/errors" + "go.uber.org/zap" +) + +var _ common.LabelCache = (*CiliumIdentityHandler)(nil) + +const ( + CiliumIdentityHandlerName = "cilium-identity-handler" +) + +// CiliumIdentityHandler watches CiliumIdentity resources using resource.Resource +type CiliumIdentityHandler struct { + identities resource.Resource[*cilium_api_v2.CiliumIdentity] + + // Internal cache for identity management + mu sync.RWMutex + labelsByIdentityID map[cid.NumericIdentity][]string + ctxCancelFunc context.CancelFunc + + logger *log.ZapLogger +} + +type CiliumIdentityHandlerParams struct { + cell.In + + Lifecycle cell.Lifecycle + Identities resource.Resource[*cilium_api_v2.CiliumIdentity] +} + +type CiliumIdentityHandlerOut struct { + cell.Out + + common.LabelCache + *CiliumIdentityHandler +} + +// NewCiliumIdentityHandler creates a new CiliumIdentityHandler instance +func NewCiliumIdentityHandler(params CiliumIdentityHandlerParams) CiliumIdentityHandlerOut { + handler := &CiliumIdentityHandler{ + identities: params.Identities, + labelsByIdentityID: make(map[cid.NumericIdentity][]string), + logger: log.Logger().Named(CiliumIdentityHandlerName), + } + + params.Lifecycle.Append(handler) + + return CiliumIdentityHandlerOut{ + LabelCache: handler, + CiliumIdentityHandler: handler, + } +} + +func (h *CiliumIdentityHandler) Start(cell.HookContext) error { + ctx, cancel := context.WithCancel(context.Background()) + h.ctxCancelFunc = cancel + go h.run(ctx) + h.logger.Info("CiliumIdentity handler started") + return nil +} + +func (h *CiliumIdentityHandler) Stop(cell.HookContext) error { + if h.ctxCancelFunc != nil { + h.ctxCancelFunc() + } + h.logger.Info("CiliumIdentity handler stopped") + return nil +} + +func (h *CiliumIdentityHandler) run(ctx context.Context) { + h.logger.Info("Starting CiliumIdentity event handler") + + identityEvents := h.identities.Events(ctx) + + for { + select { + case ev, ok := <-identityEvents: + if !ok { + h.logger.Info("CiliumIdentity events channel closed") + return + } + + h.handleEvent(ev) + ev.Done(nil) + + case <-ctx.Done(): + h.logger.Info("CiliumIdentity event handler stopped") + return + } + } +} + +func (h *CiliumIdentityHandler) handleEvent(ev resource.Event[*cilium_api_v2.CiliumIdentity]) { + switch ev.Kind { + case resource.Sync: + // Ignore sync events + h.logger.Debug("CiliumIdentity sync event received", zap.String("key", ev.Key.String())) + case resource.Upsert: + if ev.Object != nil { + h.logger.Debug("CiliumIdentity upsert event", zap.String("key", ev.Key.String())) + if err := h.updateIdentityCache(ev.Object); err != nil { + h.logger.Error("Failed to update identity cache", zap.Error(err), zap.String("key", ev.Key.String())) + } + } + case resource.Delete: + h.logger.Debug("CiliumIdentity delete event", zap.String("key", ev.Key.String())) + h.removeIdentityFromCache(ev.Key.Name) + } +} + +func (h *CiliumIdentityHandler) GetLabelsFromSecurityIdentity(id cid.NumericIdentity) []string { + h.mu.RLock() + defer h.mu.RUnlock() + // Retrieve labels from the cache + labels, exists := h.labelsByIdentityID[id] + if !exists { + h.logger.Debug("Identity not found in cache", zap.Uint32("identity", id.Uint32())) + return nil + } + h.logger.Debug("Retrieved labels from cache", zap.Uint32("identity", id.Uint32()), zap.Strings("labels", labels)) + return labels +} + +func (h *CiliumIdentityHandler) updateIdentityCache(identity *cilium_api_v2.CiliumIdentity) error { + id, err := cid.ParseNumericIdentity(identity.Name) + if err != nil { + return errors.Wrapf(err, "invalid identity name %s", identity.Name) + } + // Parse the security labels + secLabels := make([]string, 0, len(identity.SecurityLabels)) + for k, v := range identity.SecurityLabels { + secLabels = append(secLabels, k+"="+v) + } + h.mu.Lock() + defer h.mu.Unlock() + // Update the cache with the new labels + h.labelsByIdentityID[id] = secLabels + + return nil +} + +func (h *CiliumIdentityHandler) removeIdentityFromCache(name string) { + h.mu.Lock() + defer h.mu.Unlock() + + id, err := cid.ParseNumericIdentity(name) + if err != nil { + h.logger.Error("Failed to parse identity name", zap.Error(err), zap.String("identity", name)) + return + } + + if _, exists := h.labelsByIdentityID[id]; exists { + delete(h.labelsByIdentityID, id) + h.logger.Debug("Removed identity from cache", zap.String("identity", name)) + } else { + h.logger.Debug("Identity not found in cache", zap.String("identity", name)) + } +} diff --git a/pkg/hubble/resources/ciliumidentity_linux_test.go b/pkg/hubble/resources/ciliumidentity_linux_test.go new file mode 100644 index 0000000000..1b9cd7170a --- /dev/null +++ b/pkg/hubble/resources/ciliumidentity_linux_test.go @@ -0,0 +1,549 @@ +package resources + +import ( + "context" + "testing" + "time" + + cid "github.com/cilium/cilium/pkg/identity" + cilium_api_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" + "github.com/cilium/cilium/pkg/k8s/resource" + "github.com/cilium/hive/cell" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// mockIdentityResource is a test implementation of resource.Resource[*cilium_api_v2.CiliumIdentity] +type mockIdentityResource struct { + eventChan chan resource.Event[*cilium_api_v2.CiliumIdentity] +} + +func newMockIdentityResource() *mockIdentityResource { + return &mockIdentityResource{ + eventChan: make(chan resource.Event[*cilium_api_v2.CiliumIdentity], 100), + } +} + +func (m *mockIdentityResource) Events(context.Context, ...resource.EventsOpt) <-chan resource.Event[*cilium_api_v2.CiliumIdentity] { + return m.eventChan +} + +func (m *mockIdentityResource) Observe(context.Context, func(resource.Event[*cilium_api_v2.CiliumIdentity]), func(error)) { +} + +func (m *mockIdentityResource) Store(context.Context) (resource.Store[*cilium_api_v2.CiliumIdentity], error) { + return nil, nil +} + +func (m *mockIdentityResource) sendEvent(kind resource.EventKind, identity *cilium_api_v2.CiliumIdentity) { + key := resource.Key{} + if identity != nil { + key.Name = identity.Name + key.Namespace = identity.Namespace + } + + done := make(chan error, 1) + m.eventChan <- resource.Event[*cilium_api_v2.CiliumIdentity]{ + Kind: kind, + Key: key, + Object: identity, + Done: func(err error) { done <- err }, + } + // Wait for event to be processed + <-done +} + +func (m *mockIdentityResource) close() { + close(m.eventChan) +} + +func TestNewCiliumIdentityHandler(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + + assert.NotNil(t, handlerOut.CiliumIdentityHandler) + assert.NotNil(t, handlerOut.LabelCache) + assert.NotNil(t, handlerOut.labelsByIdentityID) + assert.NotNil(t, handlerOut.logger) + assert.Equal(t, CiliumIdentityHandlerName, handlerOut.logger.Name()) +} + +func TestCiliumIdentityHandler_EventHandling_IdentityCreated(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "123", + }, + SecurityLabels: map[string]string{ + "k8s:app": "nginx", + "k8s:version": "1.0", + "k8s:tier": "frontend", + }, + } + + mockRes.sendEvent(resource.Upsert, identity) + time.Sleep(10 * time.Millisecond) + + // Verify the identity was cached + expectedID := cid.NumericIdentity(123) + labels := handler.GetLabelsFromSecurityIdentity(expectedID) + require.NotNil(t, labels) + assert.Len(t, labels, 3) + assert.Contains(t, labels, "k8s:app=nginx") + assert.Contains(t, labels, "k8s:version=1.0") + assert.Contains(t, labels, "k8s:tier=frontend") +} + +func TestCiliumIdentityHandler_EventHandling_IdentityUpdated(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + // Initial identity + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "456", + }, + SecurityLabels: map[string]string{ + "k8s:app": "nginx", + }, + } + + mockRes.sendEvent(resource.Upsert, identity) + time.Sleep(10 * time.Millisecond) + + // Update the identity with new labels + updatedIdentity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "456", + }, + SecurityLabels: map[string]string{ + "k8s:app": "nginx", + "k8s:version": "2.0", + }, + } + + mockRes.sendEvent(resource.Upsert, updatedIdentity) + time.Sleep(10 * time.Millisecond) + + // Verify the updated labels in cache + expectedID := cid.NumericIdentity(456) + labels := handler.GetLabelsFromSecurityIdentity(expectedID) + require.NotNil(t, labels) + assert.Len(t, labels, 2) + assert.Contains(t, labels, "k8s:app=nginx") + assert.Contains(t, labels, "k8s:version=2.0") +} + +func TestCiliumIdentityHandler_EventHandling_IdentityDeleted(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + // Create identity first + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "789", + }, + SecurityLabels: map[string]string{ + "k8s:app": "test", + }, + } + + mockRes.sendEvent(resource.Upsert, identity) + time.Sleep(10 * time.Millisecond) + + // Delete the identity + mockRes.sendEvent(resource.Delete, identity) + time.Sleep(10 * time.Millisecond) + + // Verify the identity was removed from cache + expectedID := cid.NumericIdentity(789) + labels := handler.GetLabelsFromSecurityIdentity(expectedID) + assert.Nil(t, labels) +} + +func TestCiliumIdentityHandler_EventHandling_InvalidIdentityName(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "invalid-name", + }, + SecurityLabels: map[string]string{ + "k8s:app": "test", + }, + } + + // This should not panic, just log an error + mockRes.sendEvent(resource.Upsert, identity) + time.Sleep(10 * time.Millisecond) + + // Cache should be empty + handler.mu.RLock() + defer handler.mu.RUnlock() + assert.Empty(t, handler.labelsByIdentityID) +} + +func TestCiliumIdentityHandler_GetLabelsFromSecurityIdentity(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + // Test case 1: Identity exists in cache + expectedID := cid.NumericIdentity(100) + expectedLabels := []string{"k8s:app=nginx", "k8s:version=1.0"} + handler.mu.Lock() + handler.labelsByIdentityID[expectedID] = expectedLabels + handler.mu.Unlock() + + labels := handler.GetLabelsFromSecurityIdentity(expectedID) + assert.Equal(t, expectedLabels, labels) + + // Test case 2: Identity does not exist in cache + nonExistentID := cid.NumericIdentity(404) + labels = handler.GetLabelsFromSecurityIdentity(nonExistentID) + assert.Nil(t, labels) +} + +func TestCiliumIdentityHandler_updateIdentityCache(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "200", + }, + SecurityLabels: map[string]string{ + "k8s:app": "web", + "k8s:tier": "frontend", + "security": "restricted", + }, + } + + err := handler.updateIdentityCache(identity) + require.NoError(t, err) + + // Verify the cache was updated + expectedID := cid.NumericIdentity(200) + labels := handler.GetLabelsFromSecurityIdentity(expectedID) + require.NotNil(t, labels) + assert.Len(t, labels, 3) + assert.Contains(t, labels, "k8s:app=web") + assert.Contains(t, labels, "k8s:tier=frontend") + assert.Contains(t, labels, "security=restricted") +} + +func TestCiliumIdentityHandler_updateIdentityCache_InvalidName(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "not-a-number", + }, + SecurityLabels: map[string]string{ + "k8s:app": "test", + }, + } + + err := handler.updateIdentityCache(identity) + require.Error(t, err) + assert.Contains(t, err.Error(), "invalid identity name") +} + +func TestCiliumIdentityHandler_removeIdentityFromCache(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + // Pre-populate cache + expectedID := cid.NumericIdentity(300) + handler.mu.Lock() + handler.labelsByIdentityID[expectedID] = []string{"k8s:app=test"} + handler.mu.Unlock() + + // Test removal + handler.removeIdentityFromCache("300") + + // Verify removal + labels := handler.GetLabelsFromSecurityIdentity(expectedID) + assert.Nil(t, labels) +} + +func TestCiliumIdentityHandler_removeIdentityFromCache_InvalidName(_ *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + // This should not panic even with invalid name + handler.removeIdentityFromCache("invalid-name") + + // No assertions needed, just ensure it doesn't panic +} + +func TestCiliumIdentityHandler_removeIdentityFromCache_NotInCache(_ *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + // Try to remove identity that doesn't exist in cache + handler.removeIdentityFromCache("404") + + // No assertions needed, just ensure it doesn't panic +} + +func TestCiliumIdentityHandler_SyncEvent(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "123", + }, + SecurityLabels: map[string]string{ + "k8s:app": "test", + }, + } + + // Send sync event (should be ignored) + mockRes.sendEvent(resource.Sync, identity) + time.Sleep(10 * time.Millisecond) + + // Verify cache is empty + handler.mu.RLock() + defer handler.mu.RUnlock() + + assert.Empty(t, handler.labelsByIdentityID) +} + +func TestCiliumIdentityHandler_ConcurrentAccess(t *testing.T) { + mockRes := newMockIdentityResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + identity := &cilium_api_v2.CiliumIdentity{ + ObjectMeta: metav1.ObjectMeta{ + Name: "500", + }, + SecurityLabels: map[string]string{ + "k8s:app": "test", + "k8s:version": "1.0", + }, + } + + // Test concurrent read/write access + done := make(chan bool, 2) + + // Goroutine 1: Send event + go func() { + mockRes.sendEvent(resource.Upsert, identity) + done <- true + }() + + // Goroutine 2: Read from cache + go func() { + time.Sleep(5 * time.Millisecond) + identityID := cid.NumericIdentity(500) + handler.GetLabelsFromSecurityIdentity(identityID) + done <- true + }() + + // Wait for both goroutines to complete + <-done + <-done + + time.Sleep(10 * time.Millisecond) + + // Verify final state + identityID := cid.NumericIdentity(500) + labels := handler.GetLabelsFromSecurityIdentity(identityID) + require.NotNil(t, labels) + assert.Len(t, labels, 2) + assert.Contains(t, labels, "k8s:app=test") + assert.Contains(t, labels, "k8s:version=1.0") +} + +func TestCiliumIdentityHandler_StopClosesChannel(t *testing.T) { + mockRes := newMockIdentityResource() + + lc := &cell.DefaultLifecycle{} + params := CiliumIdentityHandlerParams{ + Lifecycle: lc, + Identities: mockRes, + } + + handlerOut := NewCiliumIdentityHandler(params) + handler := handlerOut.CiliumIdentityHandler + + ctx, cancel := context.WithCancel(context.Background()) + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + // Close the mock resource + mockRes.close() + time.Sleep(10 * time.Millisecond) + + // Stop should complete without error + err = handler.Stop(ctx) + require.NoError(t, err) + + cancel() +} diff --git a/pkg/hubble/resources/service_linux.go b/pkg/hubble/resources/service_linux.go new file mode 100644 index 0000000000..fe26c26ce0 --- /dev/null +++ b/pkg/hubble/resources/service_linux.go @@ -0,0 +1,195 @@ +package resources + +import ( + "context" + "net/netip" + "sync" + + "github.com/cilium/cilium/api/v1/flow" + "github.com/cilium/cilium/pkg/k8s/resource" + slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" + "github.com/cilium/hive/cell" + "github.com/microsoft/retina/pkg/hubble/common" + "github.com/microsoft/retina/pkg/log" + "go.uber.org/zap" + "k8s.io/apimachinery/pkg/types" +) + +var _ common.SvcDecoder = (*ServiceHandler)(nil) + +const ( + ServiceHandlerName = "k8s-service-handler" +) + +// ServiceHandler watches Kubernetes services using resource.Resource +type ServiceHandler struct { + services resource.Resource[*slim_corev1.Service] + + // Internal cache for services and their IPs + mu sync.RWMutex + ipToService map[string]*flow.Service // Maps IP to *flow.Service + serviceToIPs map[types.NamespacedName][]string // Maps service key to its IPs + ctxCancelFunc context.CancelFunc + + logger *log.ZapLogger +} + +type ServiceHandlerParams struct { + cell.In + + Lifecycle cell.Lifecycle + Services resource.Resource[*slim_corev1.Service] +} + +type ServiceHandlerOut struct { + cell.Out + + common.SvcDecoder + *ServiceHandler +} + +// NewServiceHandler creates a new ServiceHandler instance +func NewServiceHandler(params ServiceHandlerParams) ServiceHandlerOut { + handler := &ServiceHandler{ + services: params.Services, + ipToService: make(map[string]*flow.Service), + serviceToIPs: make(map[types.NamespacedName][]string), + logger: log.Logger().Named(ServiceHandlerName), + } + + params.Lifecycle.Append(handler) + + return ServiceHandlerOut{ + SvcDecoder: handler, + ServiceHandler: handler, + } +} + +func (h *ServiceHandler) Start(cell.HookContext) error { + ctx, cancel := context.WithCancel(context.Background()) + h.ctxCancelFunc = cancel + go h.run(ctx) + h.logger.Info("Service handler started") + return nil +} + +func (h *ServiceHandler) Stop(cell.HookContext) error { + if h.ctxCancelFunc != nil { + h.ctxCancelFunc() + } + h.logger.Info("Service handler stopped") + return nil +} + +func (h *ServiceHandler) run(ctx context.Context) { + h.logger.Info("Starting service event handler") + + serviceEvents := h.services.Events(ctx) + + for { + select { + case ev, ok := <-serviceEvents: + if !ok { + h.logger.Info("Service events channel closed") + return + } + + h.handleEvent(ev) + ev.Done(nil) + + case <-ctx.Done(): + h.logger.Info("Service event handler stopped") + return + } + } +} + +func (h *ServiceHandler) handleEvent(ev resource.Event[*slim_corev1.Service]) { + switch ev.Kind { + case resource.Sync: + // Ignore sync events + h.logger.Debug("Service sync event received", zap.String("key", ev.Key.String())) + case resource.Upsert: + if ev.Object != nil { + h.logger.Debug("Service upsert event", zap.String("key", ev.Key.String())) + h.updateServiceCache(ev.Object) + } + case resource.Delete: + h.logger.Debug("Service delete event", zap.String("key", ev.Key.String())) + h.removeServiceFromCache(ev.Key.Namespace, ev.Key.Name) + } +} + +// Decode returns the service associated with the given IP address, or nil if not found. +func (h *ServiceHandler) Decode(ip netip.Addr) *flow.Service { + h.mu.RLock() + defer h.mu.RUnlock() + + return h.ipToService[ip.String()] +} + +// updateServiceCache updates the internal service cache +func (h *ServiceHandler) updateServiceCache(service *slim_corev1.Service) { + h.mu.Lock() + defer h.mu.Unlock() + + key := types.NamespacedName{ + Namespace: service.Namespace, + Name: service.Name, + } + + // Remove old IP mappings first + if oldIPs, exists := h.serviceToIPs[key]; exists { + for _, oldIP := range oldIPs { + delete(h.ipToService, oldIP) + } + } + + // Update IP mappings with new values + h.addServiceIPMappings(service) + + h.logger.Debug("Updated service cache", + zap.String("service", key.String()), + zap.Strings("clusterIPs", service.Spec.ClusterIPs)) +} + +// removeServiceFromCache removes a service from the cache +func (h *ServiceHandler) removeServiceFromCache(namespace, name string) { + h.mu.Lock() + defer h.mu.Unlock() + + serviceKey := types.NamespacedName{ + Namespace: namespace, + Name: name, + } + + if ips, exists := h.serviceToIPs[serviceKey]; exists { + for _, ip := range ips { + delete(h.ipToService, ip) + } + delete(h.serviceToIPs, serviceKey) + } +} + +// addServiceIPMappings adds IP to service mappings +func (h *ServiceHandler) addServiceIPMappings(service *slim_corev1.Service) { + key := types.NamespacedName{ + Namespace: service.Namespace, + Name: service.Name, + } + + flowService := &flow.Service{ + Name: service.Name, + Namespace: service.Namespace, + } + + h.serviceToIPs[key] = []string{} + + // Add ClusterIP mapping + for _, clusterIP := range service.Spec.ClusterIPs { + if clusterIP != "" && clusterIP != "None" { + h.ipToService[clusterIP] = flowService // Use the same cached object + h.serviceToIPs[key] = append(h.serviceToIPs[key], clusterIP) + } + } +} diff --git a/pkg/hubble/resources/service_linux_test.go b/pkg/hubble/resources/service_linux_test.go new file mode 100644 index 0000000000..602f0e95f0 --- /dev/null +++ b/pkg/hubble/resources/service_linux_test.go @@ -0,0 +1,516 @@ +package resources + +import ( + "context" + "net/netip" + "testing" + "time" + + "github.com/cilium/cilium/api/v1/flow" + "github.com/cilium/cilium/pkg/k8s/resource" + slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" + slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" + "github.com/cilium/hive/cell" + "github.com/microsoft/retina/pkg/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/types" +) + +func init() { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) +} + +// mockServiceResource is a test implementation of resource.Resource[*slim_corev1.Service] +type mockServiceResource struct { + eventChan chan resource.Event[*slim_corev1.Service] +} + +func newMockServiceResource() *mockServiceResource { + return &mockServiceResource{ + eventChan: make(chan resource.Event[*slim_corev1.Service], 100), + } +} + +func (m *mockServiceResource) Events(context.Context, ...resource.EventsOpt) <-chan resource.Event[*slim_corev1.Service] { + return m.eventChan +} + +func (m *mockServiceResource) Observe(context.Context, func(resource.Event[*slim_corev1.Service]), func(error)) { +} + +func (m *mockServiceResource) Store(context.Context) (resource.Store[*slim_corev1.Service], error) { + return nil, nil +} + +func (m *mockServiceResource) sendEvent(kind resource.EventKind, svc *slim_corev1.Service) { + key := resource.Key{} + if svc != nil { + key.Name = svc.Name + key.Namespace = svc.Namespace + } + + done := make(chan error, 1) + m.eventChan <- resource.Event[*slim_corev1.Service]{ + Kind: kind, + Key: key, + Object: svc, + Done: func(err error) { done <- err }, + } + // Wait for event to be processed + <-done +} + +func (m *mockServiceResource) close() { + close(m.eventChan) +} + +func TestNewServiceHandler(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + + assert.NotNil(t, handlerOut.ServiceHandler) + assert.NotNil(t, handlerOut.SvcDecoder) + assert.NotNil(t, handlerOut.ipToService) + assert.NotNil(t, handlerOut.serviceToIPs) + assert.NotNil(t, handlerOut.logger) + assert.Equal(t, ServiceHandlerName, handlerOut.logger.Name()) +} + +func TestServiceHandler_EventHandling_ServiceCreated(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + // Start the handler + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + + // Give the handler time to start + time.Sleep(10 * time.Millisecond) + + service := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "test-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"10.96.0.1", "10.96.0.2"}, + }, + } + + // Send upsert event + mockRes.sendEvent(resource.Upsert, service) + + // Give the handler time to process + time.Sleep(10 * time.Millisecond) + + // Verify the service is cached + handler.mu.RLock() + defer handler.mu.RUnlock() + + expectedKey := types.NamespacedName{Name: "test-service", Namespace: "default"} + assert.Contains(t, handler.ipToService, "10.96.0.1") + assert.Contains(t, handler.ipToService, "10.96.0.2") + + flowService1 := handler.ipToService["10.96.0.1"] + flowService2 := handler.ipToService["10.96.0.2"] + assert.Equal(t, "test-service", flowService1.GetName()) + assert.Equal(t, "default", flowService1.GetNamespace()) + assert.Same(t, flowService1, flowService2) + + assert.Contains(t, handler.serviceToIPs, expectedKey) + assert.ElementsMatch(t, []string{"10.96.0.1", "10.96.0.2"}, handler.serviceToIPs[expectedKey]) +} + +func TestServiceHandler_EventHandling_ServiceUpdated(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + // Initial service + service := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "test-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"10.96.0.1", "10.96.0.2"}, + }, + } + + mockRes.sendEvent(resource.Upsert, service) + time.Sleep(10 * time.Millisecond) + + // Update service with new IPs + updatedService := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "test-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"10.96.0.3", "10.96.0.4"}, + }, + } + + mockRes.sendEvent(resource.Upsert, updatedService) + time.Sleep(10 * time.Millisecond) + + // Verify cache is updated + handler.mu.RLock() + defer handler.mu.RUnlock() + + expectedKey := types.NamespacedName{Name: "test-service", Namespace: "default"} + + // Old IPs should be gone + assert.NotContains(t, handler.ipToService, "10.96.0.1") + assert.NotContains(t, handler.ipToService, "10.96.0.2") + + // New IPs should be present + assert.Contains(t, handler.ipToService, "10.96.0.3") + assert.Contains(t, handler.ipToService, "10.96.0.4") + + flowService := handler.ipToService["10.96.0.3"] + assert.Equal(t, "test-service", flowService.GetName()) + assert.Equal(t, "default", flowService.GetNamespace()) + + assert.Contains(t, handler.serviceToIPs, expectedKey) + assert.ElementsMatch(t, []string{"10.96.0.3", "10.96.0.4"}, handler.serviceToIPs[expectedKey]) +} + +func TestServiceHandler_EventHandling_ServiceDeleted(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + // Create service first + service := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "test-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"10.96.0.1", "10.96.0.2"}, + }, + } + + mockRes.sendEvent(resource.Upsert, service) + time.Sleep(10 * time.Millisecond) + + // Delete service + mockRes.sendEvent(resource.Delete, service) + time.Sleep(10 * time.Millisecond) + + // Verify cache is cleared + handler.mu.RLock() + defer handler.mu.RUnlock() + + serviceKey := types.NamespacedName{Name: "test-service", Namespace: "default"} + assert.NotContains(t, handler.ipToService, "10.96.0.1") + assert.NotContains(t, handler.ipToService, "10.96.0.2") + assert.NotContains(t, handler.serviceToIPs, serviceKey) +} + +func TestServiceHandler_EventHandling_HeadlessService(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + service := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "headless-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"None"}, + }, + } + + mockRes.sendEvent(resource.Upsert, service) + time.Sleep(10 * time.Millisecond) + + // Verify no IPs are cached for headless service + handler.mu.RLock() + defer handler.mu.RUnlock() + + expectedKey := types.NamespacedName{Name: "headless-service", Namespace: "default"} + assert.NotContains(t, handler.ipToService, "None") + assert.Contains(t, handler.serviceToIPs, expectedKey) + assert.Empty(t, handler.serviceToIPs[expectedKey]) +} + +func TestServiceHandler_Decode_ExistingIP(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + // Pre-populate cache + serviceKey := types.NamespacedName{Name: "test-service", Namespace: "default"} + flowService := &flow.Service{Name: "test-service", Namespace: "default"} + handler.mu.Lock() + handler.ipToService["10.96.0.1"] = flowService + handler.serviceToIPs[serviceKey] = []string{"10.96.0.1"} + handler.mu.Unlock() + + ip, _ := netip.ParseAddr("10.96.0.1") + result := handler.Decode(ip) + + require.NotNil(t, result) + assert.Equal(t, "test-service", result.GetName()) + assert.Equal(t, "default", result.GetNamespace()) + assert.Same(t, flowService, result) +} + +func TestServiceHandler_Decode_NonExistingIP(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ip, _ := netip.ParseAddr("10.96.0.100") + result := handler.Decode(ip) + + assert.Nil(t, result) +} + +func TestServiceHandler_Decode_IPv6(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + // Pre-populate cache with IPv6 + serviceKey := types.NamespacedName{Name: "test-service-v6", Namespace: "kube-system"} + flowService := &flow.Service{Name: "test-service-v6", Namespace: "kube-system"} + handler.mu.Lock() + handler.ipToService["fd00::1"] = flowService + handler.serviceToIPs[serviceKey] = []string{"fd00::1"} + handler.mu.Unlock() + + ip, _ := netip.ParseAddr("fd00::1") + result := handler.Decode(ip) + + require.NotNil(t, result) + assert.Equal(t, "test-service-v6", result.GetName()) + assert.Equal(t, "kube-system", result.GetNamespace()) + assert.Same(t, flowService, result) +} + +func TestServiceHandler_SyncEvent(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + service := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "test-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"10.96.0.1"}, + }, + } + + // Send sync event (should be ignored) + mockRes.sendEvent(resource.Sync, service) + time.Sleep(10 * time.Millisecond) + + // Verify cache is empty + handler.mu.RLock() + defer handler.mu.RUnlock() + + assert.Empty(t, handler.ipToService) + assert.Empty(t, handler.serviceToIPs) +} + +func TestServiceHandler_ConcurrentAccess(t *testing.T) { + mockRes := newMockServiceResource() + defer mockRes.close() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + service := &slim_corev1.Service{ + ObjectMeta: slim_metav1.ObjectMeta{ + Name: "concurrent-test-service", + Namespace: "default", + }, + Spec: slim_corev1.ServiceSpec{ + ClusterIPs: []string{"10.100.0.1"}, + }, + } + + // Test concurrent read/write access + done := make(chan bool, 2) + + // Goroutine 1: Send event + go func() { + mockRes.sendEvent(resource.Upsert, service) + done <- true + }() + + // Goroutine 2: Read from cache + go func() { + time.Sleep(5 * time.Millisecond) + ip, _ := netip.ParseAddr("10.100.0.1") + handler.Decode(ip) + done <- true + }() + + // Wait for both goroutines to complete + <-done + <-done + + time.Sleep(10 * time.Millisecond) + + // Verify final state + ip, _ := netip.ParseAddr("10.100.0.1") + result := handler.Decode(ip) + + require.NotNil(t, result) + assert.Equal(t, "concurrent-test-service", result.GetName()) + assert.Equal(t, "default", result.GetNamespace()) +} + +func TestServiceHandler_StopClosesChannel(t *testing.T) { + mockRes := newMockServiceResource() + + lc := &cell.DefaultLifecycle{} + params := ServiceHandlerParams{ + Lifecycle: lc, + Services: mockRes, + } + + handlerOut := NewServiceHandler(params) + handler := handlerOut.ServiceHandler + + ctx, cancel := context.WithCancel(context.Background()) + + err := handler.Start(ctx) + require.NoError(t, err) + time.Sleep(10 * time.Millisecond) + + // Close the mock resource + mockRes.close() + time.Sleep(10 * time.Millisecond) + + // Stop should complete without error + err = handler.Stop(ctx) + require.NoError(t, err) + + cancel() +} From e502680b3f160945673712f0dad8daf4f0d19945 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 09:58:45 -0500 Subject: [PATCH 186/448] deps: bump github.com/go-chi/chi/v5 from 5.2.2 to 5.2.3 (#1985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.2 to 5.2.3.
Release notes

Sourced from github.com/go-chi/chi/v5's releases.

v5.2.3

What's Changed

New Contributors

Full Changelog: https://github.com/go-chi/chi/compare/v5.2.2...v5.2.3

Commits
  • 9b9fb55 Replace methodTypString func with reverseMethodMap (#1018)
  • 0265fcd refactor: iterative wildcard collapsing and add test for consecutive wildcard...
  • cf537d4 Optimize throttle middleware by avoiding unnecessary timer creation (#1011)
  • 9040e95 fix/608 - Fix flaky Throttle middleware test by synchronizing token usage (#1...
  • d12cc49 feat(mux): support http.Request.Pattern in Go 1.23 (#986)
  • 1c2d011 Avoid potential nil dereference (#1008)
  • 7859137 Allow multiple whitespace between method & pattern (#1013)
  • 80d8da2 Add pathvalue example to README and implement PathValue handler. (#985)
  • See full diff in compare view

Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | github.com/go-chi/chi/v5 | [< 5.1, > 5.0.11] |
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-chi/chi/v5&package-manager=go_modules&previous-version=5.2.2&new-version=5.2.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4505de7861..9396ab7d84 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/microsoft/retina go 1.24.11 require ( - github.com/go-chi/chi/v5 v5.2.2 + github.com/go-chi/chi/v5 v5.2.3 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.23.0 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index fd1a0a8d05..debe6ac1b4 100644 --- a/go.sum +++ b/go.sum @@ -575,8 +575,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= From 304f9305b876634dc08edd9829fd4955fc570d3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 14:27:17 -0500 Subject: [PATCH 187/448] chore(deps): bump golang.org/x/crypto from 0.36.0 to 0.45.0 in /test/multicloud/test in the go_modules group across 1 directory (#1991) Bumps the go_modules group with 1 update in the /test/multicloud/test directory: [golang.org/x/crypto](https://github.com/golang/crypto). Updates `golang.org/x/crypto` from 0.36.0 to 0.45.0
Commits
  • 4e0068c go.mod: update golang.org/x dependencies
  • e79546e ssh: curb GSSAPI DoS risk by limiting number of specified OIDs
  • f91f7a7 ssh/agent: prevent panic on malformed constraint
  • 2df4153 acme/autocert: let automatic renewal work with short lifetime certs
  • bcf6a84 acme: pass context to request
  • b4f2b62 ssh: fix error message on unsupported cipher
  • 79ec3a5 ssh: allow to bind to a hostname in remote forwarding
  • 122a78f go.mod: update golang.org/x dependencies
  • c0531f9 all: eliminate vet diagnostics
  • 0997000 all: fix some comments
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/crypto&package-manager=go_modules&previous-version=0.36.0&new-version=0.45.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/multicloud/test/go.mod | 16 ++++++++-------- test/multicloud/test/go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/multicloud/test/go.mod b/test/multicloud/test/go.mod index 036b464491..cd76ece8e3 100644 --- a/test/multicloud/test/go.mod +++ b/test/multicloud/test/go.mod @@ -53,16 +53,16 @@ require ( github.com/ulikunitz/xz v0.5.14 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zclconf/go-cty v1.15.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.38.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.38.0 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/test/multicloud/test/go.sum b/test/multicloud/test/go.sum index 3ae36de007..5334673c05 100644 --- a/test/multicloud/test/go.sum +++ b/test/multicloud/test/go.sum @@ -132,44 +132,44 @@ github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmB 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= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= 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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= 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.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= 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= From 0e7fd9997e1bba3d00af948db9a7c3c53c73880e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Jan 2026 19:00:09 -0500 Subject: [PATCH 188/448] deps: bump github.com/safchain/ethtool from 0.6.2 to 0.7.0 (#1992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/safchain/ethtool](https://github.com/safchain/ethtool) from 0.6.2 to 0.7.0.
Release notes

Sourced from github.com/safchain/ethtool's releases.

v0.7.0

What's Changed

Full Changelog: https://github.com/safchain/ethtool/compare/v0.6.2...v0.7.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/safchain/ethtool&package-manager=go_modules&previous-version=0.6.2&new-version=0.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9396ab7d84..8ac66249b5 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.17.0 - golang.org/x/sys v0.37.0 + golang.org/x/sys v0.38.0 golang.org/x/term v0.34.0 // indirect google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 // indirect @@ -297,7 +297,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.65.0 - github.com/safchain/ethtool v0.6.2 + github.com/safchain/ethtool v0.7.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 diff --git a/go.sum b/go.sum index debe6ac1b4..0d2b0c7119 100644 --- a/go.sum +++ b/go.sum @@ -1305,8 +1305,8 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a h1:np2nR32/A/VcOG9Hn+IOPA8kMk1gbBzK5LpSsgq5pJI= github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a/go.mod h1:wiP6GQ2T378F+YIyuNw7yXtBxJZR+fqrrn1Z6UHZi0Q= -github.com/safchain/ethtool v0.6.2 h1:O3ZPFAKEUEfbtE6J/feEe2Ft7dIJ2Sy8t4SdMRiIMHY= -github.com/safchain/ethtool v0.6.2/go.mod h1:VS7cn+bP3Px3rIq55xImBiZGHVLNyBh5dqG6dDQy8+I= +github.com/safchain/ethtool v0.7.0 h1:rlJzfDetsVvT61uz8x1YIcFn12akMfuPulHtZjtb7Is= +github.com/safchain/ethtool v0.7.0/go.mod h1:MenQKEjXdfkjD3mp2QdCk8B/hwvkrlOTm/FD4gTpFxQ= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= @@ -1780,8 +1780,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From 38857b779ccbbea0a839dc16df21382ee296a51b Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:53:08 +0000 Subject: [PATCH 189/448] feat(cli): Target pod for capture (#1990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Implement support for capturing network traffic on specific pods by name using the `--pod-names` flag in kubectl retina CLI. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Live Cluster Testing (5 comprehensive scenarios): - Single pod capture with traffic filtering (1,872 packets captured) - Non-existent pod error handling (0 packets when target not involved) - Complex 3-pod multi-directional traffic (1,772 packets with correct exclusion) - Multiple pod targeting with OR-logic filtering (930 packets) - 4-pod perfect isolation test - verified pod-3↔pod-4 traffic (0 packets) excluded when neither targeted Unit Test Coverage (28 test cases): - Mutual exclusivity validation between pod-names and other selectors (6 cases) - Pod name resolution with single/multiple pods, IPv4/IPv6 support (10 cases) - Capture target aggregation on nodes (4 cases) - CLI flag parsing and CRD structure generation (8 cases) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/cmd/capture/capture.go | 1 + cli/cmd/capture/create.go | 23 +- cli/cmd/capture/create_test.go | 177 +++++++++++ crd/api/v1alpha1/capture_types.go | 6 + docs/04-Captures/02-cli.md | 28 +- docs/04-Captures/03-crd.md | 41 +++ docs/05-Concepts/CRDs/Capture.md | 2 +- pkg/capture/crd_to_job.go | 59 +++- pkg/capture/crd_to_job_test.go | 480 +++++++++++++++++++++++++++++- 9 files changed, 802 insertions(+), 15 deletions(-) diff --git a/cli/cmd/capture/capture.go b/cli/cmd/capture/capture.go index 082edb4d5e..70cafa7e55 100644 --- a/cli/cmd/capture/capture.go +++ b/cli/cmd/capture/capture.go @@ -29,6 +29,7 @@ type Opts struct { nodeSelectors string nowait bool packetSize int + podNames string podSelectors string pvc string s3AccessKeyID string diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index e7863aa5ed..0669abb7ed 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -55,6 +55,12 @@ var createExample = templates.Examples(i18n.T(` # Select pods determined by pod-selectors and namespace-selectors kubectl retina capture create --namespace capture --pod-selectors="k8s-app=kube-dns" --namespace-selectors="kubernetes.io/metadata.name=kube-system" + # Select specific pods by name + kubectl retina capture create --namespace default --pod-names "pod1,pod2" --duration 30s + + # Select a single pod by name + kubectl retina capture create --namespace myapp --pod-names "my-app-pod-abc123" --duration 60s + # Select nodes with label "agentpool=agentpool" and "version:v20" kubectl retina capture create --node-selectors="agentpool=agentpool,version:v20" @@ -193,6 +199,8 @@ func NewCreateSubCommand(kubeClient kubernetes.Interface) *cobra.Command { createCapture.Flags().IntVar(&opts.packetSize, "packet-size", DefaultPacketSize, "Limits the each packet to bytes in size which works only for Linux") createCapture.Flags().StringVar(&opts.nodeNames, "node-names", "", "A comma-separated list of node names to select nodes on which the network capture will be performed") createCapture.Flags().StringVar(&opts.nodeSelectors, "node-selectors", DefaultNodeSelectors, "A comma-separated list of node labels to select nodes on which the network capture will be performed") + createCapture.Flags().StringVar(&opts.podNames, "pod-names", "", + "A comma-separated list of pod names to select specific pods on which the network capture will be performed (must be in the specified namespace)") createCapture.Flags().StringVar(&opts.podSelectors, "pod-selectors", "", "A comma-separated list of pod labels to select pods on which the network capture will be performed") createCapture.Flags().StringVar(&opts.namespaceSelectors, "namespace-selectors", "", @@ -298,10 +306,11 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti capture.Spec.CaptureConfiguration.CaptureOption.Duration = &metav1.Duration{Duration: opts.duration} } - if opts.namespaceSelectors != "" || opts.podSelectors != "" { + if opts.namespaceSelectors != "" || opts.podSelectors != "" || opts.podNames != "" { // if node selector is using the default value (aka hasn't been set by user), set it to nil to prevent clash with namespace and pod selector if opts.nodeSelectors == DefaultNodeSelectors { - retinacmd.Logger.Info("Overriding default node selectors value and setting it to nil. Using namespace and pod selectors. To use node selector, please remove namespace and pod selectors.") + retinacmd.Logger.Info("Overriding default node selectors value and setting it to nil. Using namespace, pod selectors, or pod names. " + + "To use node selector, please remove namespace and pod selectors.") opts.nodeSelectors = "" } } @@ -350,6 +359,16 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti } } + // Add pod names if provided + if opts.podNames != "" { + podNameSlice := strings.Split(opts.podNames, ",") + for i := range podNameSlice { + podNameSlice[i] = strings.TrimSpace(podNameSlice[i]) + } + retinacmd.Logger.Info(fmt.Sprintf("Capturing on specific pods: %v", podNameSlice)) + capture.Spec.CaptureConfiguration.CaptureTarget.PodNames = podNameSlice + } + if opts.maxSize != 0 { retinacmd.Logger.Info(fmt.Sprintf("The capture file max size is set to %dMB", opts.maxSize)) capture.Spec.CaptureConfiguration.CaptureOption.MaxCaptureSize = &opts.maxSize diff --git a/cli/cmd/capture/create_test.go b/cli/cmd/capture/create_test.go index 1eed7c85eb..e2d3906586 100644 --- a/cli/cmd/capture/create_test.go +++ b/cli/cmd/capture/create_test.go @@ -10,7 +10,9 @@ import ( "math/rand" "testing" + retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" "github.com/microsoft/retina/pkg/label" + "github.com/stretchr/testify/require" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -333,3 +335,178 @@ func JobsCreatedCorrectly(t *testing.T, kubeClient *fake.Clientset, tc testcase) t.Errorf("Job's node affinity doesn't match expected nodes. Expected: %v", tc.wantNodes) } } + +// Pod Names Tests - Tests for CLI pod name selection functionality + +func TestCreateCaptureCommand_PodNamesWithNodeSelector_ShouldFail(t *testing.T) { + // Test that when pod-names is specified with node-selectors, the node selector is overridden + // and the command attempts to use pod names. Since the pod doesn't exist, this will fail. + // This verifies that pod names take precedence over default node selectors. + cmd := NewCommand(fake.NewClientset()) + + cmd.SetArgs([]string{ + "create", + "--name=test-capture", + "--namespace=default", + "--pod-names=nonexistent-pod", + "--node-selectors=kubernetes.io/os=linux", + "--duration=10s", + "--host-path=/tmp/capture", + }) + + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + err := cmd.Execute() + require.Error(t, err, "command should fail when pod-names specifies a nonexistent pod") + require.Contains(t, err.Error(), "not found", "error should indicate the pod was not found") +} + +func TestCreateCaptureWithPodNames_CRDStructure(t *testing.T) { + // Table-driven test for pod names CRD structure generation + cases := []struct { + name string + podNames []string + namespace string + wantSelector bool + }{ + { + name: "single pod name", + podNames: []string{"test-pod"}, + namespace: "default", + wantSelector: true, + }, + { + name: "multiple pod names", + podNames: []string{"pod1", "pod2", "pod3"}, + namespace: "myapp", + wantSelector: true, + }, + { + name: "no pod names", + podNames: nil, + namespace: "default", + wantSelector: false, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture", + Namespace: tc.namespace, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + PodNames: tc.podNames, + }, + }, + }, + } + + require.NotNil(t, capture) + require.Equal(t, tc.namespace, capture.Namespace) + + if tc.wantSelector { + require.NotNil(t, capture.Spec.CaptureConfiguration.CaptureTarget.PodNames) + require.Equal(t, tc.podNames, capture.Spec.CaptureConfiguration.CaptureTarget.PodNames) + require.Nil(t, capture.Spec.CaptureConfiguration.CaptureTarget.NodeSelector) + } else { + require.Nil(t, capture.Spec.CaptureConfiguration.CaptureTarget.PodNames) + } + }) + } +} + +func TestCaptureTarget_PodNames_MutualExclusivity(t *testing.T) { + // Comprehensive test for mutual exclusivity constraints between pod names and other selectors + cases := []struct { + name string + target retinav1alpha1.CaptureTarget + isValid bool + }{ + { + name: "pod names only", + target: retinav1alpha1.CaptureTarget{ + PodNames: []string{"pod1", "pod2"}, + }, + isValid: true, + }, + { + name: "pod names with node selector", + target: retinav1alpha1.CaptureTarget{ + PodNames: []string{"pod1"}, + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"kubernetes.io/os": "linux"}, + }, + }, + isValid: false, + }, + { + name: "pod names with pod selector", + target: retinav1alpha1.CaptureTarget{ + PodNames: []string{"pod1"}, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "test"}, + }, + }, + isValid: false, + }, + { + name: "pod names with namespace selector", + target: retinav1alpha1.CaptureTarget{ + PodNames: []string{"pod1"}, + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"name": "default"}, + }, + }, + isValid: false, + }, + { + name: "node selector only", + target: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"kubernetes.io/os": "linux"}, + }, + }, + isValid: true, + }, + { + name: "pod and namespace selectors", + target: retinav1alpha1.CaptureTarget{ + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "test"}, + }, + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"name": "default"}, + }, + }, + isValid: true, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture", + Namespace: "default", + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: tc.target, + }, + }, + } + + require.NotNil(t, capture) + if tc.isValid { + t.Logf("✓ Valid selector combination: %s", tc.name) + } else { + t.Logf("✓ Invalid selector combination (will be caught by validation): %s", tc.name) + } + }) + } +} diff --git a/crd/api/v1alpha1/capture_types.go b/crd/api/v1alpha1/capture_types.go index 917305830a..e5fa45ec09 100644 --- a/crd/api/v1alpha1/capture_types.go +++ b/crd/api/v1alpha1/capture_types.go @@ -91,6 +91,12 @@ type CaptureTarget struct { // selector semantics. // +optional PodSelector *metav1.LabelSelector `json:"podSelector,omitempty"` + + // PodNames allows selecting specific pods by their names. + // If specified, the capture will be performed on the pods with matching names in the specified namespace. + // PodNames is incompatible with NodeSelector, NamespaceSelector, and PodSelector. + // +optional + PodNames []string `json:"podNames,omitempty"` } // CaptureConfiguration indicates the configurations of the network capture. diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index 7822f5f91f..dd42ad59be 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -24,9 +24,13 @@ The target indicates where the packet capture will be performed. This can be set - `--node-selectors` - `--node-names` -- `--pod-selectors` and `--namespace-selectors` (pairs) +- `--pod-names` (for specific pods) +- `--pod-selectors` and `--namespace-selectors` (pairs for label-based pod selection) -Note that Node Selectors are not compatible with Pod Selectors & Namespace Selectors pairs and the capture will not go through if all are populated. +Note that the following combinations are not allowed: + +- Node Selectors are not compatible with Pod Selectors & Namespace Selectors pairs +- Pod Names are not compatible with Node Selectors, Pod Selectors, or Namespace Selectors If nothing is set, `kubectl retina capture create` will use `--node-selectors` with the default value shown below in [Flags](#flags). @@ -71,6 +75,7 @@ The network traffic will be uploaded to the specified output location. | `node-selectors` | string | kubernetes.io/os=linux | A comma-separated list of node labels to select nodes on which the network capture will be performed. | | | `no-wait` | bool | true | By default, Retina capture CLI will exit before the jobs are completed. If false, the CLI will wait until the jobs are completed and clean up the Kubernetes resources created. | | | `packet-size` | int | 0 | Limit the packet size in bytes. Packets longer than the defined maximum size will be truncated. The default value 0 indicates no limit. This is beneficial when the user wants to reduce the capture file size or hide customer data due to security concerns. | Only works on Linux. | +| `pod-names` | string | "" | A comma-separated list of specific pod names to select pods on which the network capture will be performed. | Mutually exclusive with `node-selectors`, `pod-selectors`, and `namespace-selectors`. | | `pod-selectors` | string | "" | A comma-separated list of pod labels to select pods on which the network capture will be performed. | Pair with `namespace-selectors`. | | `pvc` | string | "" | PersistentVolumeClaim under the specified or default namespace to store capture files. | | | `s3-access-key-id` | string | "" | S3 access key id to upload capture files. | | @@ -111,6 +116,25 @@ kubectl retina capture create \ --namespace-selectors="kubernetes.io/metadata.name=kube-system" ``` +Pod Names (Specific Pods) + +```sh +kubectl retina capture create \ + --name example-pod-names \ + --namespace myapp \ + --pod-names "my-app-pod-abc123,my-app-pod-def456" +``` + +Single Pod by Name + +```sh +kubectl retina capture create \ + --name example-single-pod \ + --namespace myapp \ + --pod-names "my-app-pod-abc123" \ + --duration 60s +``` + ##### Interface Selection Capture on all interfaces (default behavior) diff --git a/docs/04-Captures/03-crd.md b/docs/04-Captures/03-crd.md index 3212aba1e6..ca5f17d80a 100644 --- a/docs/04-Captures/03-crd.md +++ b/docs/04-Captures/03-crd.md @@ -108,4 +108,45 @@ spec: hostPath: /captures ``` +Single Pod by Name + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: example-pod-names + namespace: myapp +spec: + captureConfiguration: + captureOption: + duration: "60s" + maxCaptureSize: 100 + captureTarget: + podNames: + - my-app-pod-abc123 + outputConfiguration: + hostPath: /captures +``` + +Multiple Pods by Name + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: example-multiple-pod-names + namespace: myapp +spec: + captureConfiguration: + captureOption: + duration: "30s" + maxCaptureSize: 100 + captureTarget: + podNames: + - my-app-pod-abc123 + - my-app-pod-def456 + outputConfiguration: + hostPath: /captures +``` + Additional examples can also be found in the [GitHub capture samples](https://github.com/microsoft/retina/tree/main/samples/capture). diff --git a/docs/05-Concepts/CRDs/Capture.md b/docs/05-Concepts/CRDs/Capture.md index c5e31db1fe..a7f08d013e 100644 --- a/docs/05-Concepts/CRDs/Capture.md +++ b/docs/05-Concepts/CRDs/Capture.md @@ -24,7 +24,7 @@ The `Capture` CRD is defined with the following specifications: - **spec.captureConfiguration:** Specifies the configuration for capturing network packets. It includes the following properties: - `captureOption`: Lists options for the capture, such as duration, maximum capture size, and packet size. - - `captureTarget`: Defines the target on which the network packets will be captured. It includes namespace, node, and pod selectors. + - `captureTarget`: Defines the target on which the network packets will be captured. It includes namespace, node, and pod selectors, as well as specific pod names. - `filters`: Specifies filters for including or excluding network packets based on IP or port. - `includeMetadata`: Indicates whether networking metadata should be captured. - `tcpdumpFilter`: Allows specifying a raw tcpdump filter string. diff --git a/pkg/capture/crd_to_job.go b/pkg/capture/crd_to_job.go index eeb5b9a000..ebc00b3f5f 100644 --- a/pkg/capture/crd_to_job.go +++ b/pkg/capture/crd_to_job.go @@ -5,6 +5,7 @@ package capture import ( "context" + "errors" "fmt" "net" "sort" @@ -32,6 +33,13 @@ import ( const anyIPOrPort = "" +var ( + errNoTargetsSelected = errors.New("no targets are selected by node selector, pod selector, or pod names") + errNoValidSelector = errors.New("neither NodeSelector, NamespaceSelector&PodSelector, nor PodNames is set") + errNodeSelectorIncompat = errors.New("NodeSelector is not compatible with NamespaceSelector&PodSelector or PodNames, please use one or the other") + errPodNamesIncompat = errors.New("PodNames is not compatible with NamespaceSelector or PodSelector, please use one or the other") +) + // CaptureTarget indicates on which the network capture will be performed on a given node. type CaptureTarget struct { // PodIpAddresses indicates the capture is performed on the Pods per their IP addresses. @@ -358,7 +366,7 @@ func (translator *CaptureToPodTranslator) TranslateCaptureToJobs(ctx context.Con if err := translator.initJobTemplate(ctx, capture); err != nil { return nil, err } - captureTargetOnNode, err := translator.CalculateCaptureTargetsOnNode(ctx, capture.Spec.CaptureConfiguration.CaptureTarget) + captureTargetOnNode, err := translator.CalculateCaptureTargetsOnNode(ctx, capture.Spec.CaptureConfiguration.CaptureTarget, capture.Namespace) if err != nil { return nil, err } @@ -540,12 +548,16 @@ func getNetshFilterWithPodIPAddress(podIPAddresses []string) string { // validateTargetSelector validate target selectors defined in the capture. func (translator *CaptureToPodTranslator) validateTargetSelector(captureTarget retinav1alpha1.CaptureTarget) error { // When NamespaceSelector is nil while PodSelector is specified, the namespace will be determined by capture.Namespace. - if captureTarget.NodeSelector == nil && captureTarget.PodSelector == nil { - return fmt.Errorf("Neither NodeSelector nor NamespaceSelector&PodSelector is set.") + if captureTarget.NodeSelector == nil && captureTarget.PodSelector == nil && len(captureTarget.PodNames) == 0 { + return errNoValidSelector } - if captureTarget.NodeSelector != nil && (captureTarget.NamespaceSelector != nil || captureTarget.PodSelector != nil) { - return fmt.Errorf("NodeSelector is not compatible with NamespaceSelector&PodSelector. Please use one or the other.") + if captureTarget.NodeSelector != nil && (captureTarget.NamespaceSelector != nil || captureTarget.PodSelector != nil || len(captureTarget.PodNames) > 0) { + return errNodeSelectorIncompat + } + + if len(captureTarget.PodNames) > 0 && (captureTarget.NamespaceSelector != nil || captureTarget.PodSelector != nil) { + return errPodNamesIncompat } return nil @@ -570,7 +582,7 @@ func (translator *CaptureToPodTranslator) validateCapture(capture *retinav1alpha return nil } -func (translator *CaptureToPodTranslator) getCaptureTargetsOnNode(ctx context.Context, captureTarget retinav1alpha1.CaptureTarget) (*CaptureTargetsOnNode, error) { +func (translator *CaptureToPodTranslator) getCaptureTargetsOnNode(ctx context.Context, captureTarget retinav1alpha1.CaptureTarget, namespace string) (*CaptureTargetsOnNode, error) { var err error captureTargetsOnNode := &CaptureTargetsOnNode{} if captureTarget.NodeSelector != nil { @@ -583,9 +595,14 @@ func (translator *CaptureToPodTranslator) getCaptureTargetsOnNode(ctx context.Co return nil, err } } + if len(captureTarget.PodNames) > 0 { + if captureTargetsOnNode, err = translator.calculateCaptureTargetsByPodNames(ctx, captureTarget, namespace); err != nil { + return nil, err + } + } if len(*captureTargetsOnNode) == 0 { - return nil, fmt.Errorf("no targets are selected by node selector or pod selector") + return nil, errNoTargetsSelected } return captureTargetsOnNode, nil } @@ -619,12 +636,12 @@ func (translator *CaptureToPodTranslator) updateCaptureTargetsOSOnNode(ctx conte } // CalculateCaptureTargetsOnNode returns capture target on each node. -func (translator *CaptureToPodTranslator) CalculateCaptureTargetsOnNode(ctx context.Context, captureTarget retinav1alpha1.CaptureTarget) (*CaptureTargetsOnNode, error) { +func (translator *CaptureToPodTranslator) CalculateCaptureTargetsOnNode(ctx context.Context, captureTarget retinav1alpha1.CaptureTarget, namespace string) (*CaptureTargetsOnNode, error) { if err := translator.validateTargetSelector(captureTarget); err != nil { return nil, err } - captureTargetsOnNode, err := translator.getCaptureTargetsOnNode(ctx, captureTarget) + captureTargetsOnNode, err := translator.getCaptureTargetsOnNode(ctx, captureTarget, namespace) if err != nil { return nil, err } @@ -713,6 +730,30 @@ func (translator *CaptureToPodTranslator) calculateCaptureTargetsByPodSelector(c return captureTargetOnNode, nil } +func (translator *CaptureToPodTranslator) calculateCaptureTargetsByPodNames(ctx context.Context, captureTarget retinav1alpha1.CaptureTarget, namespace string) (*CaptureTargetsOnNode, error) { + captureTargetOnNode := &CaptureTargetsOnNode{} + + // Get the pods by their names from the specified namespace + for _, podName := range captureTarget.PodNames { + pod, err := translator.kubeClient.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{}) + if err != nil { + translator.l.Error("Failed to get Pod by name", zap.String("podName", podName), zap.String("namespace", namespace), zap.Error(err)) + return nil, fmt.Errorf("failed to get pod %s in namespace %s: %w", podName, namespace, err) + } + + // We want to include all the ip addresses assigned to the Pod in case the Pod is selected. + // This may happen when a pod is allocated with IPv4 and IPv6 addresses. + // And Pod.Status.PodIPs must include pod.Status.PodIP. + podIPs := []string{} + for _, podIP := range pod.Status.PodIPs { + podIPs = append(podIPs, podIP.IP) + } + captureTargetOnNode.AddPod(pod.Spec.NodeName, podIPs) + } + + return captureTargetOnNode, nil +} + // For tcpdump, we put each filter(ip:port) into parentheses, and all include filters will be grouped in parentheses, // same case for exclude filters, finally the filters overall will be like: // ((include1) or (include2)) and not ((exclude1) or (exclude2)) diff --git a/pkg/capture/crd_to_job_test.go b/pkg/capture/crd_to_job_test.go index df5eeae735..76604f6f66 100644 --- a/pkg/capture/crd_to_job_test.go +++ b/pkg/capture/crd_to_job_test.go @@ -4,6 +4,7 @@ package capture import ( + "context" "fmt" "strconv" "testing" @@ -396,7 +397,7 @@ func Test_CaptureToPodTranslator_GetCaptureTargetsOnNode(t *testing.T) { k8sClient := fakeclientset.NewSimpleClientset(objects...) captureToPodTranslator := NewCaptureToPodTranslatorForTest(k8sClient) - gotCaptureTargetsOnNode, err := captureToPodTranslator.getCaptureTargetsOnNode(ctx, tt.captureTarget) + gotCaptureTargetsOnNode, err := captureToPodTranslator.getCaptureTargetsOnNode(ctx, tt.captureTarget, "default") if tt.wantErr != (err != nil) { t.Errorf("getCaptureTargetsOnNode() want(%t) error, got error %s", tt.wantErr, err) } @@ -2261,3 +2262,480 @@ func TestGetNetshFilterWithPodIPAddress(t *testing.T) { }) } } + +// Pod Names Tests - Tests for capturing by specific pod names + +func TestValidateTargetSelector_PodNames(t *testing.T) { + cases := []struct { + name string + captureTarget retinav1alpha1.CaptureTarget + wantErr bool + errMsg string + }{ + { + name: "valid pod names only", + captureTarget: retinav1alpha1.CaptureTarget{ + PodNames: []string{"pod1", "pod2"}, + }, + wantErr: false, + }, + { + name: "pod names with node selector should fail", + captureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{}, + PodNames: []string{"pod1"}, + }, + wantErr: true, + errMsg: "not compatible with", + }, + { + name: "pod names with pod selector should fail", + captureTarget: retinav1alpha1.CaptureTarget{ + PodSelector: &metav1.LabelSelector{}, + PodNames: []string{"pod1"}, + }, + wantErr: true, + errMsg: "not compatible with", + }, + { + name: "pod names with namespace selector should fail", + captureTarget: retinav1alpha1.CaptureTarget{ + NamespaceSelector: &metav1.LabelSelector{}, + PodNames: []string{"pod1"}, + }, + wantErr: true, + errMsg: "not compatible with", + }, + { + name: "node selector only should pass", + captureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{}, + }, + wantErr: false, + }, + { + name: "neither selector nor pod names should fail", + captureTarget: retinav1alpha1.CaptureTarget{ + PodNames: []string{}, + }, + wantErr: true, + errMsg: "neither", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + kubeClient := fakeclientset.NewClientset() + translator := NewCaptureToPodTranslatorForTest(kubeClient) + err := translator.validateTargetSelector(tc.captureTarget) + if tc.wantErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestCalculateCaptureTargetsByPodNames(t *testing.T) { + // Combined test for pod name resolution including basic and edge cases + cases := []struct { + name string + podNames []string + namespace string + pods []*corev1.Pod + wantErr bool + wantTargets map[string][]string // node -> pod IPs + errMsg string + }{ + // Basic cases + { + name: "single pod by name", + podNames: []string{"test-pod-1"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1"}, + }, + }, + { + name: "multiple pods by name", + podNames: []string{"test-pod-1", "test-pod-2"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-2", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node2"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.2"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1"}, + "node2": {"10.0.0.2"}, + }, + }, + { + name: "pod not found", + podNames: []string{"nonexistent-pod"}, + namespace: "default", + pods: []*corev1.Pod{}, + wantErr: true, + errMsg: "failed to get pod", + }, + // Edge cases + { + name: "pod with multiple IP addresses", + podNames: []string{"test-pod-1"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}, {IP: "fd00::1"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1", "fd00::1"}, + }, + }, + { + name: "pods on same node", + podNames: []string{"test-pod-1", "test-pod-2"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-2", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.2"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1", "10.0.0.2"}, + }, + }, + { + name: "pod with no IP addresses", + podNames: []string{"test-pod-1"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{PodIPs: []corev1.PodIP{}}, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {}, + }, + }, + { + name: "multiple pods on different nodes", + podNames: []string{"test-pod-1", "test-pod-2", "test-pod-3"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-2", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node2"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.2"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-3", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node3"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.3"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1"}, + "node2": {"10.0.0.2"}, + "node3": {"10.0.0.3"}, + }, + }, + { + name: "pod with IPv4 and IPv6 addresses", + podNames: []string{"test-pod-1"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}, {IP: "2001:db8::1"}, {IP: "fd00::1"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1", "2001:db8::1", "fd00::1"}, + }, + }, + { + name: "pod in different namespace", + podNames: []string{"test-pod-1"}, + namespace: "custom-ns", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "custom-ns"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1"}, + }, + }, + { + name: "multiple pods with same IP on different nodes", + podNames: []string{"test-pod-1", "test-pod-2"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-1", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node1"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "test-pod-2", Namespace: "default"}, + Spec: corev1.PodSpec{NodeName: "node2"}, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{{IP: "10.0.0.1"}}, + }, + }, + }, + wantErr: false, + wantTargets: map[string][]string{ + "node1": {"10.0.0.1"}, + "node2": {"10.0.0.1"}, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + objects := make([]runtime.Object, 0, len(tc.pods)) + for _, pod := range tc.pods { + objects = append(objects, pod) + } + kubeClient := fakeclientset.NewClientset(objects...) + translator := NewCaptureToPodTranslatorForTest(kubeClient) + + captureTarget := retinav1alpha1.CaptureTarget{ + PodNames: tc.podNames, + } + + ctx := context.Background() + targets, err := translator.calculateCaptureTargetsByPodNames(ctx, captureTarget, tc.namespace) + + if tc.wantErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } else { + require.NoError(t, err) + require.NotNil(t, targets) + + gotTargets := make(map[string][]string) + for nodeName, target := range *targets { + gotTargets[nodeName] = target.PodIpAddresses + } + + if diff := cmp.Diff(tc.wantTargets, gotTargets); diff != "" { + t.Errorf("calculateCaptureTargetsByPodNames() mismatch (-want, +got):\n%s", diff) + } + } + }) + } +} + +func TestGetCaptureTargetsOnNode_WithPodNames(t *testing.T) { + // Combined test for getCaptureTargetsOnNode and CalculateCaptureTargetsOnNode with pod names + cases := []struct { + name string + podNames []string + namespace string + pods []*corev1.Pod + wantErr bool + wantNodeLen int + }{ + { + name: "pod names with valid pods", + podNames: []string{"test-pod-1"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod-1", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + NodeName: "node1", + }, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{ + {IP: "10.0.0.1"}, + }, + }, + }, + }, + wantErr: false, + wantNodeLen: 1, + }, + { + name: "empty pod names list", + podNames: []string{}, + namespace: "default", + pods: []*corev1.Pod{}, + wantErr: true, + wantNodeLen: 0, + }, + { + name: "multiple valid pod names on different nodes", + podNames: []string{"test-pod-1", "test-pod-2"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod-1", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + NodeName: "node1", + }, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{ + {IP: "10.0.0.1"}, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod-2", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + NodeName: "node2", + }, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{ + {IP: "10.0.0.2"}, + }, + }, + }, + }, + wantErr: false, + wantNodeLen: 2, + }, + { + name: "pods on same node aggregated", + podNames: []string{"test-pod-1", "test-pod-2"}, + namespace: "default", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod-1", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + NodeName: "node1", + }, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{ + {IP: "10.0.0.1"}, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod-2", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + NodeName: "node1", + }, + Status: corev1.PodStatus{ + PodIPs: []corev1.PodIP{ + {IP: "10.0.0.2"}, + }, + }, + }, + }, + wantErr: false, + wantNodeLen: 1, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + objects := make([]runtime.Object, 0, len(tc.pods)) + for _, pod := range tc.pods { + objects = append(objects, pod) + } + kubeClient := fakeclientset.NewClientset(objects...) + translator := NewCaptureToPodTranslatorForTest(kubeClient) + + captureTarget := retinav1alpha1.CaptureTarget{ + PodNames: tc.podNames, + } + + ctx := context.Background() + targets, err := translator.getCaptureTargetsOnNode(ctx, captureTarget, tc.namespace) + + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, targets) + require.Len(t, *targets, tc.wantNodeLen) + } + }) + } +} From 4895b43b4252e059b8d29b4a1f217c8d7d1123db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:27:45 -0500 Subject: [PATCH 190/448] deps: bump actions/setup-go from 6.1.0 to 6.2.0 (#1996) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.1.0 to 6.2.0.
Release notes

Sourced from actions/setup-go's releases.

v6.2.0

What's Changed

Enhancements

Dependency updates

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.2.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=6.1.0&new-version=6.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 12 ++++++------ .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-images.yaml | 10 +++++----- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 71c664e449..64b2bdb112 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go if: env.IS_NOT_MERGE_GROUP - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - name: Initialize CodeQL diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 8477439f11..01ce930bed 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -89,7 +89,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 88ef83cd8e..c94481eb03 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,7 +24,7 @@ jobs: if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 if: env.IS_NOT_MERGE_GROUP with: go-version-file: go.mod diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 6d366e8fda..487a74a563 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -18,7 +18,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - name: Run GoReleaser build @@ -39,7 +39,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - name: Run GoReleaser release diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 99ff68e597..3185d6321c 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -25,7 +25,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -76,7 +76,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -136,7 +136,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -186,7 +186,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -235,7 +235,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -321,7 +321,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index 7cc9015d46..e99e231675 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -51,7 +51,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 14d4536cfa..bdb11bca4e 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -26,7 +26,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -72,7 +72,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -126,7 +126,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -171,7 +171,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version @@ -214,7 +214,7 @@ jobs: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 5dfb8ade3b..8bd6369654 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -71,7 +71,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 9e2600b2ba..d73a43c05e 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f8d1e1d57a..20840dfc33 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod From f760861f20986773c1054927546d8cc74d115447 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Fri, 16 Jan 2026 12:06:34 +0000 Subject: [PATCH 191/448] fix: pktmon etw silent failure (#1983) # Description Fix issue where the pktmon plugin silently fails to monitor packets when another Windows ETW consumer is active. Use independent context.Background for health check and stream opening instead of inheriting parent context Increased health check timeout from 30s to 60s to accommodate Windows pktmon startup Added ERROR level logging for stream initialization failures ### Before: Pod could crash with "context canceled" panic during shutdown Stream initialization would hang if parent context was cancelled Silent failures without visible error messages ### After: Health check completes independently even during daemon shutdown Stream initialization has independent timeout, unaffected by parent context Errors properly logged at ERROR level for debugging Pod exits gracefully instead of hanging or panicking ## Related Issue https://github.com/microsoft/retina/issues/1893 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed 1. Reproduce the Issue Deployed Retina v1.0.0 (unfixed) with pktmon plugin on AKS Windows nodes. Pod entered Running state but silently failed to monitor packets with no error messages. 2. Apply the Fix Built and pushed fixed image to ACR. #### Scenario 1 - No Traffic: Deployed pod with no network activity Verified pod stays Running (2/2 containers) Health check completed without timeout or crash Pod remained stable indefinitely #### Scenario 2 - Failure (pktmon unavailable): Killed pktmon server process to simulate failure Verified ERROR logs captured: "No connection could be made because the target machine actively refused it" Pod exited gracefully instead of hanging Kubernetes automatically restarted pod (CrashLoopBackOff) #### Scenario 3 - Success with Traffic: Fresh pod deployment with healthy pktmon Verified metrics collection active: "emitting packets/bytes count metrics" Collected metrics continuously for 70+ seconds across multiple endpoints Pod handled graceful shutdown without panic when pktmon became unavailable ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/plugin/pktmon/pktmon_windows.go | 95 ++++++- pkg/plugin/pktmon/pktmon_windows_test.go | 304 +++++++++++++++++++++++ 2 files changed, 392 insertions(+), 7 deletions(-) create mode 100644 pkg/plugin/pktmon/pktmon_windows_test.go diff --git a/pkg/plugin/pktmon/pktmon_windows.go b/pkg/plugin/pktmon/pktmon_windows.go index 4b0759f292..3edce9c552 100644 --- a/pkg/plugin/pktmon/pktmon_windows.go +++ b/pkg/plugin/pktmon/pktmon_windows.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "os/exec" + "time" "github.com/pkg/errors" @@ -26,17 +27,21 @@ import ( ) var ( - ErrNilEnricher = errors.New("enricher is nil") - ErrUnexpectedExit = errors.New("unexpected exit") - ErrNilGrpcClient = errors.New("grpc client is nil") + ErrNilEnricher = errors.New("enricher is nil") + ErrUnexpectedExit = errors.New("unexpected exit") + ErrNilGrpcClient = errors.New("grpc client is nil") + ErrStreamHealthCheckFailed = errors.New("pktmon stream health check failed - likely another ETW consumer is active or stream is broken") + ErrTooManyNilFlows = errors.New("received too many nil flows during health check - likely proto mismatch") socket = "/temp/retina-pktmon.sock" ) const ( - name = "pktmon" - connectionRetryAttempts = 5 - eventChannelSize = 1000 + name = "pktmon" + connectionRetryAttempts = 5 + eventChannelSize = 1000 + pktmonHealthCheckTimeout = 60 * time.Second + maxNilFlowsAllowed = 5 ) type Plugin struct { @@ -157,6 +162,19 @@ func (p *Plugin) Start(ctx context.Context) error { return errors.Wrapf(err, "failed to setup initial pktmon stream") } + // Start the stream before verifying + err = p.StartStream(ctx) + if err != nil { + return errors.Wrapf(err, "failed to start initial pktmon stream") + } + + // Verify that the event stream is producing events + // This detects silent ETW registration failures where another consumer is already active + err = p.verifyEventStream() + if err != nil { + return errors.Wrapf(err, "pktmon event stream health check failed") + } + // run the getflows loop g.Go(func() error { for { @@ -198,7 +216,10 @@ func (p *Plugin) StartStream(ctx context.Context) error { var err error fn := func() error { - p.stream, err = p.grpcClient.GetFlows(ctx, &observerv1.GetFlowsRequest{}) + // Use a long timeout for stream setup, independent of parent context cancellation + streamCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + p.stream, err = p.grpcClient.GetFlows(streamCtx, &observerv1.GetFlowsRequest{}) if err != nil { return errors.Wrapf(err, "failed to open pktmon stream") } @@ -212,6 +233,66 @@ func (p *Plugin) StartStream(ctx context.Context) error { return nil } +// verifyEventStream checks that the gRPC stream is responding and that events can flow. +// This detects scenarios where ETW registration silently fails because another +// consumer is already active on the EVENTS_MAP (indicated by gRPC errors). +// If the stream is healthy but no traffic is present, it logs a warning but continues. +func (p *Plugin) verifyEventStream() error { + // Create an independent background context for the health check + // This is NOT a child of the parent ctx to avoid cancellation when the parent shuts down + // while the health check is still running + healthCtx, cancel := context.WithTimeout(context.Background(), pktmonHealthCheckTimeout) + defer cancel() + + // Create a channel to receive the result + resultCh := make(chan error, 1) + + go func() { + nilFlowCount := 0 + + for { + event, err := p.stream.Recv() + if err != nil { + resultCh <- errors.Wrapf(err, "failed to receive first event during health check") + return + } + + if event.GetFlow() == nil { + nilFlowCount++ + if nilFlowCount > maxNilFlowsAllowed { + resultCh <- fmt.Errorf("exceeded max nil flows allowed: %d: %w", maxNilFlowsAllowed, ErrTooManyNilFlows) + return + } + // Skip nil flows and wait for next event + continue + } + + // Got a valid flow + resultCh <- nil + return + } + }() + + // Wait for either a successful event or timeout + select { + case <-healthCtx.Done(): + // Timeout occurred - no events received, but stream connection is working. + // This could be due to low/no traffic rather than ETW registration failure. + p.l.Warn("no events received during health check", + zap.Duration("timeout", pktmonHealthCheckTimeout), + zap.String("cause", "likely no network traffic or node is idle")) + return nil + case err := <-resultCh: + if err != nil { + // Stream error indicates ETW registration failure or connection issue + // Use %w to properly wrap for ErrorIs traversal + return fmt.Errorf("%w: %w", ErrStreamHealthCheckFailed, err) + } + p.l.Info("pktmon event stream verified - events flowing normally") + return nil + } +} + func (p *Plugin) GetFlow(ctx context.Context) error { ctx, cancel := context.WithCancel(ctx) defer cancel() diff --git a/pkg/plugin/pktmon/pktmon_windows_test.go b/pkg/plugin/pktmon/pktmon_windows_test.go new file mode 100644 index 0000000000..1c71b14670 --- /dev/null +++ b/pkg/plugin/pktmon/pktmon_windows_test.go @@ -0,0 +1,304 @@ +//go:build windows +// +build windows + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// Package pktmon tests the pktmon plugin behavior on Windows, including the event stream +// health check which detects silent ETW registration failures when another consumer +// is already active on the EVENTS_MAP. +// +// The verifyEventStream() method is critical for detecting scenarios where: +// 1. Another ETW consumer prevents the pktmon server from registering +// 2. The registration appears successful but no events are being produced +// 3. Network traffic exists but isn't being captured +// +// These tests ensure that such failures are caught early rather than resulting in +// silent data loss and misleading metrics. +package pktmon + +import ( + "context" + "errors" + "testing" + "time" + + observerv1 "github.com/cilium/cilium/api/v1/observer" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/metadata" + + "github.com/microsoft/retina/pkg/log" +) + +var ( + errEOF = errors.New("EOF") + errConnectionLost = errors.New("connection lost") +) + +// MockGetFlowsClient implements observerv1.Observer_GetFlowsClient for testing +type MockGetFlowsClient struct { + // Sequence of responses to return + // Can be: nil (nil flow), "valid" (valid flow), error, or *observerv1.Flow (explicit flow) + responses []interface{} + index int + // Control test behavior + recvDelay time.Duration + blockCh chan struct{} // If set, block recv() forever + blockFor time.Duration // If > 0, block recv() for this duration +} + +// Recv returns the next mocked response +func (m *MockGetFlowsClient) Recv() (*observerv1.GetFlowsResponse, error) { + if m.recvDelay > 0 { + time.Sleep(m.recvDelay) + } + + if m.blockCh != nil { + <-m.blockCh + } + + if m.blockFor > 0 { + time.Sleep(m.blockFor) + } + + if m.index >= len(m.responses) { + return nil, errEOF + } + + resp := m.responses[m.index] + m.index++ + + // Return error if configured + if err, ok := resp.(error); ok { + return nil, err + } + + // Return response with non-nil flow if configured + if flow, ok := resp.(*observerv1.Flow); ok { + return &observerv1.GetFlowsResponse{ResponseTypes: &observerv1.GetFlowsResponse_Flow{Flow: flow}}, nil + } + + // Handle "valid" string marker - return a valid flow for testing + if marker, ok := resp.(string); ok && marker == "valid" { + validFlow := &observerv1.Flow{ + Source: &observerv1.Endpoint{PodName: "test-src"}, + Destination: &observerv1.Endpoint{PodName: "test-dst"}, + } + return &observerv1.GetFlowsResponse{ResponseTypes: &observerv1.GetFlowsResponse_Flow{Flow: validFlow}}, nil + } + + // For test purposes, return empty GetFlowsResponse with nil Flow + return &observerv1.GetFlowsResponse{}, nil +} + +// Header implements grpc.ClientStream +func (m *MockGetFlowsClient) Header() (metadata.MD, error) { + return nil, nil +} + +// Trailer implements grpc.ClientStream +func (m *MockGetFlowsClient) Trailer() metadata.MD { + return nil +} + +// CloseSend implements grpc.ClientStream +func (m *MockGetFlowsClient) CloseSend() error { + return nil +} + +// Context implements grpc.ClientStream +func (m *MockGetFlowsClient) Context() context.Context { + return context.Background() +} + +// SendMsg implements grpc.ClientStream +func (m *MockGetFlowsClient) SendMsg(_ interface{}) error { + return nil +} + +// RecvMsg implements grpc.ClientStream +func (m *MockGetFlowsClient) RecvMsg(_ interface{}) error { + return nil +} + +// Test_verifyEventStream_NoEventsTimeout tests timeout when no events are received +// With the new behavior, no events (due to lack of traffic) should return nil, +// not an error, since the stream connection itself is healthy. +// Note: verifyEventStream() uses an independent 60-second internal timeout, +// so the test context parameter is not used for timeout control. +func Test_verifyEventStream_NoEventsTimeout(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + blockCh: make(chan struct{}), // Block forever - will timeout internally + }, + } + + start := time.Now() + err := plugin.verifyEventStream() + elapsed := time.Since(start) + + require.NoError(t, err, "verifyEventStream should return nil when no events are received (timeout due to no traffic)") + // Should timeout after approximately pktmonHealthCheckTimeout (60s) + assert.GreaterOrEqual(t, elapsed, 59*time.Second, "should wait close to the 60s health check timeout") + assert.Less(t, elapsed, 62*time.Second, "should not wait significantly longer than the 60s timeout") +} + +// Test_verifyEventStream_StreamRecvError tests error handling when Recv() fails +// Actual connection errors (not timeouts) should still fail +func Test_verifyEventStream_StreamRecvError(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + responses: []interface{}{errConnectionLost}, + }, + } + + err := plugin.verifyEventStream() + + require.Error(t, err, "verifyEventStream should fail when Recv() returns an error") +} + +// Test_verifyEventStream_NilFlow tests that occasional nil flows are skipped +// The health check should continue waiting for valid flows rather than failing immediately +func Test_verifyEventStream_NilFlow(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + // Start with nil flow, then valid flow + responses: []interface{}{nil, "valid"}, + }, + } + + err := plugin.verifyEventStream() + + require.NoError(t, err, "verifyEventStream should skip occasional nil flows and succeed when valid flow arrives") + assert.Equal(t, 2, plugin.stream.(*MockGetFlowsClient).index, + "should consume both nil and valid flow") +} + +// Test_verifyEventStream_TooManyNilFlows tests that persistent nil flows are detected as proto mismatch +func Test_verifyEventStream_TooManyNilFlows(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + // More nil flows than allowed + responses: make([]interface{}, maxNilFlowsAllowed+2), + }, + } + + err := plugin.verifyEventStream() + + require.Error(t, err, "verifyEventStream should fail when too many nil flows are received") + // The error is wrapped as ErrStreamHealthCheckFailed which contains ErrTooManyNilFlows + assert.ErrorIs(t, err, ErrStreamHealthCheckFailed, "error should be a stream health check failure") +} + +// Test_verifyEventStream_EventWithDelay tests successful reception of delayed non-nil flow +// This verifies that the health check properly waits for a valid flow even with delay +func Test_verifyEventStream_EventWithDelay(t *testing.T) { + // Create a valid flow with basic structure + validFlow := &observerv1.Flow{ + Source: &observerv1.Endpoint{PodName: "pod-1", Namespace: "default"}, + Destination: &observerv1.Endpoint{PodName: "pod-2", Namespace: "default"}, + } + + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + blockFor: 2 * time.Second, // Delay before first message + responses: []interface{}{validFlow}, // Then send valid non-nil flow + }, + } + + start := time.Now() + err := plugin.verifyEventStream() + elapsed := time.Since(start) + + require.NoError(t, err, "should succeed when valid non-nil flow eventually arrives") + assert.GreaterOrEqual(t, elapsed, 1900*time.Millisecond, "should wait at least 1.9s for blockFor delay") + assert.Less(t, elapsed, 3*time.Second, "should not wait much longer than the 2s blockFor") +} + +// Test_verifyEventStream_TimeoutExactlyAtLimit tests timeout enforcement +// When the health check timeout occurs (no traffic), it should return nil (success) +// Note: verifyEventStream() uses an independent 60-second internal context +func Test_verifyEventStream_TimeoutExactlyAtLimit(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + blockFor: pktmonHealthCheckTimeout + 100*time.Millisecond, + }, + } + + start := time.Now() + err := plugin.verifyEventStream() + elapsed := time.Since(start) + + require.NoError(t, err, "verifyEventStream should return nil when health check timeout occurs (no traffic)") + // Should timeout after approximately pktmonHealthCheckTimeout (60s) + expectedMin := pktmonHealthCheckTimeout - 500*time.Millisecond + expectedMax := pktmonHealthCheckTimeout + 2*time.Second + assert.GreaterOrEqual(t, elapsed, expectedMin, "should wait at least close to the health check timeout") + assert.Less(t, elapsed, expectedMax, "should not wait significantly longer than the health check timeout") +} + +// Test_verifyEventStream_MultipleEvents tests that verification succeeds with valid flows +func Test_verifyEventStream_MultipleEvents(t *testing.T) { + // Test that verifyEventStream succeeds when valid flows are available + validFlow := &observerv1.Flow{ + Source: &observerv1.Endpoint{PodName: "source", Namespace: "default"}, + Destination: &observerv1.Endpoint{PodName: "destination", Namespace: "default"}, + } + + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + // Multiple valid flows + responses: []interface{}{validFlow, validFlow, validFlow}, + }, + } + + err := plugin.verifyEventStream() + + require.NoError(t, err, "should succeed when valid flows are available") +} + +// Test_verifyEventStream_NoTrafficLogsWarning tests that no-traffic timeout returns success +// Note: verifyEventStream() uses an independent 60-second internal context +func Test_verifyEventStream_NoTrafficLogsWarning(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + stream: &MockGetFlowsClient{ + blockCh: make(chan struct{}), // Block forever - will timeout internally + }, + } + + err := plugin.verifyEventStream() + + require.NoError(t, err, "verifyEventStream should succeed when timeout occurs (no traffic scenario)") +} + +// Test_StartStream_WithNilGrpcClient tests error handling when grpcClient is nil +func Test_StartStream_WithNilGrpcClient(t *testing.T) { + plugin := &Plugin{ + l: NewTestLogger(), + grpcClient: nil, + } + + err := plugin.StartStream(context.Background()) + + require.Error(t, err, "StartStream should fail when grpcClient is nil") + assert.ErrorIs(t, err, ErrNilGrpcClient, "error should be ErrNilGrpcClient") +} + +// Helper function to create a test logger +func NewTestLogger() *log.ZapLogger { + // Create a simple logger for testing + testLogger, _ := log.SetupZapLogger(&log.LogOpts{ + Level: "info", + File: false, + }) + return testLogger +} From fd482c08818b21b4d5515647382f71085b353528 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Tue, 27 Jan 2026 16:10:20 +0000 Subject: [PATCH 192/448] fix: CVE-2013-3900 - Updates to Windows image (#1997) # Description This PR tackles CVE-2013-3900 which is present on the Windows images. The Windows registry must be updated to mitigate the CVE, thus we had to separate the our Windows/Linux build process, so that Windows runs on a Windows host VM. The Windows image build step is now separate into two steps. The binaries are built as part of a separate Makefile target. The GitHub Action runs this on an Ubuntu host (intentionally - its faster than on Windows). The Windows 2019/2022 image build actions then use those binaries to complete the build on their respective Windows based hosts. ## Related Issue https://msrc.microsoft.com/update-guide/vulnerability/CVE-2013-3900 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [] I have updated the documentation, if necessary. - [] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Vulnerability scan on pre-fix Windows 2022. `ghcr.io/microsoft/retina/retina-agent:4895b43-windows-ltsc2022-amd64` image Vulnerability scan after the fix. Doesn't detect the same CVE. `ghcr.io/kamilprz/retina/retina-agent:357857e-windows-ltsc2022-amd64` image ## Additional Notes Add any additional notes or context about the pull request here. --------- Signed-off-by: Kamil --- .github/workflows/images.yaml | 75 +++++++++++++------ Makefile | 53 ++++++++++--- controller/Dockerfile | 24 +----- controller/Dockerfile.windows-2019 | 44 +++++------ controller/Dockerfile.windows-2022 | 43 +++++------ .../Dockerfile.windows-retina-oss-build | 7 +- 6 files changed, 142 insertions(+), 104 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 3185d6321c..17b60ffe78 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -13,7 +13,7 @@ permissions: jobs: retina-images: - name: Build Agent Images + name: Build Agent Images - Linux runs-on: ubuntu-latest strategy: @@ -62,27 +62,59 @@ jobs: env: IS_MERGE_GROUP: ${{ github.event_name == 'merge_group' }} - retina-win-images: - name: Build Agent Windows Images + build-windows-binaries: + name: Build Windows Binaries runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + - run: go version + + - name: Build Windows Binaries + shell: bash + run: | + TAG=$(make version) + echo "TAG=$TAG" >> $GITHUB_ENV + make build-windows-binaries \ + GOOS=windows \ + GOARCH=amd64 \ + TAG=$TAG \ + APP_INSIGHTS_ID=${{ secrets.AZURE_APP_INSIGHTS_KEY }} + env: + APP_INSIGHTS_ID: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} + + - name: Upload Windows Binaries + uses: actions/upload-artifact@v4 + with: + name: windows-binaries + path: output/windows_amd64/ + retention-days: 1 + + retina-image-win: + name: Build Agent Image - Windows ${{ matrix.year }} + needs: build-windows-binaries + runs-on: windows-${{ matrix.year }} strategy: matrix: + year: ["2019", "2022"] platform: ["windows"] arch: ["amd64"] - year: ["2019", "2022"] steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - name: Download Windows Binaries + uses: actions/download-artifact@v4 with: - go-version-file: go.mod - - run: go version - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + name: windows-binaries + path: output/windows_amd64/ - name: Az CLI login uses: azure/login@v2 @@ -91,34 +123,31 @@ jobs: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION }} - - - run: df -h - - name: "node-cleanup" - run: | - sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL - sudo docker image prune --all --force - sudo docker builder prune -a - - run: df -h - name: Build Images shell: bash run: | set -euo pipefail - echo "TAG=$(make version)" >> $GITHUB_ENV + TAG=$(make version) + echo "TAG=$TAG" >> "$GITHUB_ENV" if [ "$IS_MERGE_GROUP" == "true" ]; then az acr login -n ${{ vars.ACR_NAME }} make retina-image-win \ IMAGE_NAMESPACE=${{ github.repository }} \ PLATFORM=${{ matrix.platform }}/${{ matrix.arch }} \ + WINDOWS_YEARS=${{ matrix.year }} \ IMAGE_REGISTRY=${{ vars.ACR_NAME }} \ APP_INSIGHTS_ID=${{ secrets.AZURE_APP_INSIGHTS_KEY }} \ - WINDOWS_YEARS=${{ matrix.year }} \ - BUILDX_ACTION=--push + BINARIES_PATH=output/windows_${{ matrix.arch }} \ + REPO_PATH=. + docker push ${{ vars.ACR_NAME }}/${{ github.repository }}/retina-agent:${TAG}-windows-ltsc${{ matrix.year }}-${{ matrix.arch }} else make retina-image-win \ IMAGE_NAMESPACE=${{ github.repository }} \ PLATFORM=${{ matrix.platform }}/${{ matrix.arch }} \ - WINDOWS_YEARS=${{ matrix.year }} + WINDOWS_YEARS=${{ matrix.year }} \ + BINARIES_PATH=output/windows_${{ matrix.arch }} \ + REPO_PATH=. fi env: IS_MERGE_GROUP: ${{ github.event_name == 'merge_group' }} @@ -278,7 +307,7 @@ jobs: needs: [ retina-images, - retina-win-images, + retina-image-win, operator-images, retina-shell-images, kubectl-retina-images, diff --git a/Makefile b/Makefile index 9d8b350e82..b29dd3b2b6 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ RETINA_PLATFORM_TAG ?= $(TAG)-$(subst /,-,$(PLATFORM)) # used for looping through components in container build AGENT_TARGETS ?= init agent -WINDOWS_YEARS ?= "2019 2022" +WINDOWS_YEARS ?= 2019 2022 # for windows os, add year to the platform tag ifeq ($(OS),windows) @@ -214,7 +214,6 @@ buildx: fi; - container-docker: buildx # util target to build container images using docker buildx. do not invoke directly. os=$$(echo $(PLATFORM) | cut -d'/' -f1); \ arch=$$(echo $(PLATFORM) | cut -d'/' -f2); \ @@ -239,6 +238,27 @@ container-docker: buildx # util target to build container images using docker bu $(BUILDX_ACTION) \ $(CONTEXT_DIR) +container-docker-windows: # util target to build Windows container images without buildx. do not invoke directly. + os=$$(echo $(PLATFORM) | cut -d'/' -f1); \ + arch=$$(echo $(PLATFORM) | cut -d'/' -f2); \ + image_name=$$(basename $(IMAGE)); \ + echo "Building $$image_name for $$os/$$arch "; \ + docker build \ + --platform $(PLATFORM) \ + -f $(DOCKERFILE) \ + --build-arg BUILDPLATFORM=$(PLATFORM) \ + --build-arg APP_INSIGHTS_ID=$(APP_INSIGHTS_ID) \ + --build-arg GOARCH=$$arch \ + --build-arg GOOS=$$os \ + --build-arg OS_VERSION=$(OS_VERSION) \ + --build-arg HUBBLE_VERSION=$(HUBBLE_VERSION) \ + --build-arg VERSION=$(VERSION) \ + --build-arg REPO_PATH=$(REPO_PATH) \ + --build-arg BINARIES_PATH=$(BINARIES_PATH) \ + $(EXTRA_BUILD_ARGS) \ + --target=$(TARGET) \ + -t $(IMAGE_REGISTRY)/$(IMAGE):$(TAG) \ + $(CONTEXT_DIR) retina-image: ## build the retina linux container image. echo "Building for $(PLATFORM)" @@ -261,20 +281,24 @@ retina-image: ## build the retina linux container image. TARGET=$$target; \ done -retina-image-win: ## build the retina Windows container image. +retina-image-win: build-windows-binaries ## build the retina Windows container image. +# The Windows images are built on a corresponding Windows host without buildx. +# This is done to mitigate CVE-2013-3900. for year in $(WINDOWS_YEARS); do \ tag=$(TAG)-windows-ltsc$$year-amd64; \ - echo "Building $(RETINA_PLATFORM_TAG)"; \ + echo "Building $$tag"; \ set -e ; \ - $(MAKE) container-$(CONTAINER_BUILDER) \ + $(MAKE) container-docker-windows \ PLATFORM=windows/amd64 \ - DOCKERFILE=controller/Dockerfile \ + DOCKERFILE=controller/Dockerfile.windows-$$year \ REGISTRY=$(IMAGE_REGISTRY) \ IMAGE=$(RETINA_IMAGE) \ OS_VERSION=ltsc$$year \ VERSION=$(TAG) \ TAG=$$tag \ TARGET=agent-win \ + REPO_PATH=$(REPO_PATH) \ + BINARIES_PATH=$(BINARIES_PATH) \ CONTEXT_DIR=$(REPO_ROOT); \ done @@ -361,9 +385,20 @@ all-gen: ## generate all code $(MAKE) proto-gen $(MAKE) go-gen -build-windows-binaries: - GOOS=windows GOARCH=$(GOARCH) go build -v -o /go/bin/retina/captureworkload -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=$(TAG) -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID=$(APP_INSIGHTS_ID)" captureworkload/main.go - GOOS=windows GOARCH=$(GOARCH) go build -x -v -o /go/bin/retina/controller -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=$(TAG) -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID=$(APP_INSIGHTS_ID)" controller/main.go +build-windows-binaries: ## Build Windows binaries + @echo "Building Windows binaries for $(GOARCH)..." + @mkdir -p $(BUILD_DIR) + CGO_ENABLED=0 GOOS=windows GOARCH=$(GOARCH) go build -v \ + -o $(BUILD_DIR)/captureworkload.exe \ + -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=$(TAG) \ + -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID=$(APP_INSIGHTS_ID)" \ + $(CAPTURE_WORKLOAD_DIR)/main.go + CGO_ENABLED=0 GOOS=windows GOARCH=$(GOARCH) go build -v \ + -o $(BUILD_DIR)/controller.exe \ + -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=$(TAG) \ + -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID=$(APP_INSIGHTS_ID)" \ + $(RETINA_DIR)/main.go + @echo "Windows binaries built successfully in $(BUILD_DIR)" ##@ Multiplatform diff --git a/controller/Dockerfile b/controller/Dockerfile index ddca538728..9c651af253 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,5 +1,3 @@ -# Only applicable for windows images -ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" @@ -11,12 +9,6 @@ FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599a # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS azurelinux-distroless -# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca AS ltsc2019 - -# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 - # build stages # intermediate go generate stage @@ -54,7 +46,6 @@ ENV GOARCH=${GOARCH} ENV GOOS=${GOOS} RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /go/bin/retina/captureworkload -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID="$APP_INSIGHTS_ID"" captureworkload/main.go - # controller binary FROM intermediate AS controller-bin ARG APP_INSIGHTS_ID # set to enable AI telemetry @@ -65,7 +56,6 @@ ENV GOARCH=${GOARCH} ENV GOOS=${GOOS} RUN --mount=type=cache,target="/root/.cache/go-build" go build -x -v -o /go/bin/retina/controller -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID="$APP_INSIGHTS_ID"" controller/main.go - # init binary FROM intermediate AS init-bin ARG APP_INSIGHTS_ID # set to enable AI telemetry @@ -76,7 +66,6 @@ ENV GOARCH=${GOARCH} ENV GOOS=${GOOS} RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /go/bin/retina/initretina -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID="$APP_INSIGHTS_ID"" init/retina/main_linux.go - # tools image FROM azurelinux-core AS tools RUN tdnf install -y \ @@ -114,7 +103,6 @@ COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib ENTRYPOINT ["./retina/initretina"] - # agent final image # mcr.microsoft.com/azurelinux/distroless/minimal:3.0 # mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c @@ -129,14 +117,4 @@ COPY --from=capture-bin /go/bin/retina/captureworkload /retina/captureworkload COPY --from=tools /usr/local/hubble /bin/hubble # Set Hubble server. ENV HUBBLE_SERVER=unix:///var/run/cilium/hubble.sock -ENTRYPOINT ["./retina/controller"] - - -# agent final image for windows -FROM ${OS_VERSION} AS agent-win -COPY --from=controller-bin /go/src/github.com/microsoft/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml -COPY --from=controller-bin /go/src/github.com/microsoft/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 -COPY --from=controller-bin /go/bin/retina/controller controller.exe -COPY --from=capture-bin /go/bin/retina/captureworkload captureworkload.exe -ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe -CMD ["controller.exe", "start", "--kubeconfig=.\\kubeconfig"] +ENTRYPOINT ["./retina/controller"] \ No newline at end of file diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 index 19fb14ed3a..f54fca399b 100644 --- a/controller/Dockerfile.windows-2019 +++ b/controller/Dockerfile.windows-2019 @@ -1,28 +1,24 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder - -# Build args -ARG VERSION -ARG APP_INSIGHTS_ID - -ENV GOOS=windows -ENV GOARCH=amd64 - -WORKDIR /usr/src/retina -# Copy the source -COPY . . - -RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/controller.exe -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" ./controller/ -RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ - -# Copy into final image +# pinned base image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca as final -COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml -COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 -COPY --from=builder /usr/bin/controller.exe controller.exe -COPY --from=builder /usr/bin/captureworkload.exe captureworkload.exe +FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca AS ltsc2019 +FROM ltsc2019 AS agent-win +ARG GOARCH=amd64 # default to amd64 +ARG GOOS=windows # default to windows +ARG OS_VERSION=ltsc2019 +ARG REPO_PATH +ARG BINARIES_PATH +ENV GOARCH=${GOARCH} +ENV GOOS=${GOOS} +ENV OS_VERSION=${OS_VERSION} +ENV BINARIES_PATH=${BINARIES_PATH} +ENV REPO_PATH=${REPO_PATH} +# CVE-2013-3900 Mitigation +RUN reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f +RUN reg add "HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f +COPY ${REPO_PATH}/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml +COPY ${REPO_PATH}/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 +COPY ${BINARIES_PATH}/captureworkload.exe captureworkload.exe +COPY ${BINARIES_PATH}/controller.exe controller.exe ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe - CMD ["controller.exe", "start", "--kubeconfig=.\\kubeconfig"] diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index a797e47338..555ecf1e71 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,27 +1,24 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder - -# Build args -ARG VERSION -ARG APP_INSIGHTS_ID - -ENV GOOS=windows -ENV GOARCH=amd64 - -WORKDIR /usr/src/retina -# Copy the source -COPY . . - -RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/controller.exe -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" ./controller/ -RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /usr/bin/captureworkload.exe ./captureworkload/ - +# pinned base image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 as final -COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml -COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 -COPY --from=builder /usr/bin/controller.exe controller.exe -COPY --from=builder /usr/bin/captureworkload.exe captureworkload.exe +FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 +FROM ltsc2022 AS agent-win +ARG GOARCH=amd64 # default to amd64 +ARG GOOS=windows # default to windows +ARG OS_VERSION=ltsc2022 +ARG REPO_PATH +ARG BINARIES_PATH +ENV GOARCH=${GOARCH} +ENV GOOS=${GOOS} +ENV OS_VERSION=${OS_VERSION} +ENV BINARIES_PATH=${BINARIES_PATH} +ENV REPO_PATH=${REPO_PATH} +# CVE-2013-3900 Mitigation +RUN reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f +RUN reg add "HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f +COPY ${REPO_PATH}/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml +COPY ${REPO_PATH}/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 +COPY ${BINARIES_PATH}/captureworkload.exe captureworkload.exe +COPY ${BINARIES_PATH}/controller.exe controller.exe ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe - CMD ["controller.exe", "start", "--kubeconfig=.\\kubeconfig"] diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index 72249d4fde..d6c7332fff 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -19,8 +19,11 @@ ENV GOOS=${GOOS} ENV OS_VERSION=${OS_VERSION} ENV BINARIES_PATH=${BINARIES_PATH} ENV REPO_PATH=${REPO_PATH} -COPY ${REPO_PATH}/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml -COPY ${REPO_PATH}/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 +# CVE-2013-3900 Mitigation +RUN reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f +RUN reg add "HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f +COPY ${REPO_PATH}/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml +COPY ${REPO_PATH}/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 COPY ${BINARIES_PATH}/captureworkload.exe captureworkload.exe COPY ${BINARIES_PATH}/controller.exe controller.exe ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe From 287e92ce52a6116b686d9e9e8f37b0eb00286287 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 05:31:04 +0000 Subject: [PATCH 193/448] chore(deps): bump lodash from 4.17.21 to 4.17.23 in /site in the npm_and_yarn group across 1 directory (#2001) Bumps the npm_and_yarn group with 1 update in the /site directory: [lodash](https://github.com/lodash/lodash). Updates `lodash` from 4.17.21 to 4.17.23
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lodash&package-manager=npm_and_yarn&previous-version=4.17.21&new-version=4.17.23)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 4ccd8d0815..7e5268d417 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -11049,9 +11049,10 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", From 815a0961d52a3916577439e97ebc74d0c4c45443 Mon Sep 17 00:00:00 2001 From: kamilprz <36544756+kamilprz@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:37:22 +0000 Subject: [PATCH 194/448] fix: Release Container Images action for Windows (#2003) # Description As part of PR #1997 I introduced changes to how the Windows images are built. This was not carried over into the 'Release Container Images' job and thus it failed after the PR was merged. image This PR addresses that. I ran the action on my branch and everything was green. image ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. --------- Signed-off-by: Kamil --- .github/workflows/release-images.yaml | 73 ++++++++++++++++++--------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index bdb11bca4e..8202858289 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -58,58 +58,83 @@ jobs: cosign sign --yes ${IMAGE_PATH}@${DIGEST} done - retina-win-images: - name: Build Agent Windows Images + build-windows-binaries: + name: Build Windows Binaries runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + - run: go version + + - name: Build Windows Binaries + shell: bash + run: | + TAG=$(make version) + echo "TAG=$TAG" >> $GITHUB_ENV + make build-windows-binaries \ + GOOS=windows \ + GOARCH=amd64 \ + TAG=$TAG + + - name: Upload Windows Binaries + uses: actions/upload-artifact@v4 + with: + name: windows-binaries + path: output/windows_amd64/ + retention-days: 1 + + retina-win-images: + name: Build Agent Image - Windows ${{ matrix.year }} + needs: build-windows-binaries + runs-on: windows-${{ matrix.year }} strategy: matrix: + year: ["2019", "2022"] platform: ["windows"] arch: ["amd64"] - year: ["2019", "2022"] steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - name: Download Windows Binaries + uses: actions/download-artifact@v4 with: - go-version-file: go.mod - - run: go version + name: windows-binaries + path: output/windows_amd64/ - name: Install Cosign uses: sigstore/cosign-installer@v4.0.0 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - - - run: df -h - - name: "node-cleanup" - run: | - sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL - sudo docker image prune --all --force - sudo docker builder prune -a - - run: df -h - name: Build/Push Images shell: bash run: | set -euo pipefail - echo "TAG=$(make version)" >> $GITHUB_ENV + TAG=$(make version) + echo "TAG=$TAG" >> "$GITHUB_ENV" make retina-image-win \ - IMAGE_NAMESPACE=${{ github.repository }} \ - PLATFORM=${{ matrix.platform }}/${{ matrix.arch }} \ - WINDOWS_YEARS=${{ matrix.year }} \ - BUILDX_ACTION=--push - + IMAGE_NAMESPACE=${{ github.repository }} \ + PLATFORM=${{ matrix.platform }}/${{ matrix.arch }} \ + WINDOWS_YEARS=${{ matrix.year }} \ + BINARIES_PATH=output/windows_${{ matrix.arch }} \ + REPO_PATH=. + docker push ghcr.io/${{ github.repository }}/retina-agent:${TAG}-windows-ltsc${{ matrix.year }}-${{ matrix.arch }} + - name: Sign container image + shell: bash run: | for image in retina-agent ; do IMAGE_PATH="ghcr.io/${{ github.repository }}/$image:$TAG-windows-ltsc${{ matrix.year }}-${{ matrix.arch }}" - DIGEST=$(jq -r '.["containerimage.digest"]' image-metadata-$image-$TAG-windows-ltsc${{ matrix.year }}-${{ matrix.arch }}.json) + DIGEST=$(docker manifest inspect $IMAGE_PATH -v | jq -r '.Descriptor.digest') cosign sign --yes ${IMAGE_PATH}@${DIGEST} done From c360ca941336afd92ac9b1f5d522552e6948673e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:02:40 +0000 Subject: [PATCH 195/448] deps: bump actions/upload-artifact from 4 to 6 (#2005) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
Release notes

Sourced from actions/upload-artifact's releases.

v6.0.0

v6 - What's new

[!IMPORTANT] actions/upload-artifact@v6 now runs on Node.js 24 (runs.using: node24) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.

Node.js 24

This release updates the runtime to Node.js 24. v5 had preliminary support for Node.js 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.

What's Changed

Full Changelog: https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0

v5.0.0

What's Changed

BREAKING CHANGE: this update supports Node v24.x. This is not a breaking change per-se but we're treating it as such.

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v4...v5.0.0

v4.6.2

What's Changed

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v4...v4.6.2

v4.6.1

What's Changed

... (truncated)

Commits
  • b7c566a Merge pull request #745 from actions/upload-artifact-v6-release
  • e516bc8 docs: correct description of Node.js 24 support in README
  • ddc45ed docs: update README to correct action name for Node.js 24 support
  • 615b319 chore: release v6.0.0 for Node.js 24 support
  • 017748b Merge pull request #744 from actions/fix-storage-blob
  • 38d4c79 chore: rebuild dist
  • 7d27270 chore: add missing license cache files for @​actions/core, @​actions/io, and mi...
  • 5f643d3 chore: update license files for @​actions/artifact@​5.0.1 dependencies
  • 1df1684 chore: update package-lock.json with @​actions/artifact@​5.0.1
  • b5b1a91 fix: update @​actions/artifact to ^5.0.0 for Node.js 24 punycode fix
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=4&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 17b60ffe78..fe6013d0ab 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -89,7 +89,7 @@ jobs: APP_INSIGHTS_ID: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} - name: Upload Windows Binaries - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: windows-binaries path: output/windows_amd64/ From e9a4b2ae0461dc6f350d7b92b03cc6f39cc50580 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 02:54:49 -0500 Subject: [PATCH 196/448] deps: bump actions/download-artifact from 4 to 7 (#2004) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 7.
Release notes

Sourced from actions/download-artifact's releases.

v7.0.0

v7 - What's new

[!IMPORTANT] actions/download-artifact@v7 now runs on Node.js 24 (runs.using: node24) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.

Node.js 24

This release updates the runtime to Node.js 24. v6 had preliminary support for Node 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.

What's Changed

New Contributors

Full Changelog: https://github.com/actions/download-artifact/compare/v6.0.0...v7.0.0

v6.0.0

What's Changed

BREAKING CHANGE: this update supports Node v24.x. This is not a breaking change per-se but we're treating it as such.

New Contributors

Full Changelog: https://github.com/actions/download-artifact/compare/v5...v6.0.0

v5.0.0

What's Changed

v5.0.0

🚨 Breaking Change

This release fixes an inconsistency in path behavior for single artifact downloads by ID. If you're downloading single artifacts by ID, the output path may change.

What Changed

... (truncated)

Commits
  • 37930b1 Merge pull request #452 from actions/download-artifact-v7-release
  • 72582b9 doc: update readme
  • 0d2ec9d chore: release v7.0.0 for Node.js 24 support
  • fd7ae8f Merge pull request #451 from actions/fix-storage-blob
  • d484700 chore: restore minimatch.dep.yml license file
  • 03a8080 chore: remove obsolete dependency license files
  • 56fe6d9 chore: update @​actions/artifact license file to 5.0.1
  • 8e3ebc4 chore: update package-lock.json with @​actions/artifact@​5.0.1
  • 1e3c4b4 fix: update @​actions/artifact to ^5.0.0 for Node.js 24 punycode fix
  • 458627d chore: use local @​actions/artifact package for Node.js 24 testing
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=4&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index fe6013d0ab..5362aa177b 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -111,7 +111,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Download Windows Binaries - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 8202858289..d3c64e4330 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -104,7 +104,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Download Windows Binaries - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: windows-binaries path: output/windows_amd64/ From 299e5f6cb34226d3f4c489b013846aab9650ac7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:50:34 -0500 Subject: [PATCH 197/448] deps: bump actions/upload-artifact from 4 to 6 (#2006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
Release notes

Sourced from actions/upload-artifact's releases.

v6.0.0

v6 - What's new

[!IMPORTANT] actions/upload-artifact@v6 now runs on Node.js 24 (runs.using: node24) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.

Node.js 24

This release updates the runtime to Node.js 24. v5 had preliminary support for Node.js 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.

What's Changed

Full Changelog: https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0

v5.0.0

What's Changed

BREAKING CHANGE: this update supports Node v24.x. This is not a breaking change per-se but we're treating it as such.

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v4...v5.0.0

v4.6.2

What's Changed

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v4...v4.6.2

v4.6.1

What's Changed

... (truncated)

Commits
  • b7c566a Merge pull request #745 from actions/upload-artifact-v6-release
  • e516bc8 docs: correct description of Node.js 24 support in README
  • ddc45ed docs: update README to correct action name for Node.js 24 support
  • 615b319 chore: release v6.0.0 for Node.js 24 support
  • 017748b Merge pull request #744 from actions/fix-storage-blob
  • 38d4c79 chore: rebuild dist
  • 7d27270 chore: add missing license cache files for @​actions/core, @​actions/io, and mi...
  • 5f643d3 chore: update license files for @​actions/artifact@​5.0.1 dependencies
  • 1df1684 chore: update package-lock.json with @​actions/artifact@​5.0.1
  • b5b1a91 fix: update @​actions/artifact to ^5.0.0 for Node.js 24 punycode fix
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=4&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index d3c64e4330..753674a544 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -82,7 +82,7 @@ jobs: TAG=$TAG - name: Upload Windows Binaries - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: windows-binaries path: output/windows_amd64/ From 123892ae156d13192b30e47d06208b67865bb90f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:11:25 -0500 Subject: [PATCH 198/448] deps: bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.4 (#2007) Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.3 to 5.2.4.
Commits

Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | github.com/go-chi/chi/v5 | [< 5.1, > 5.0.11] |
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-chi/chi/v5&package-manager=go_modules&previous-version=5.2.3&new-version=5.2.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8ac66249b5..327f4afffc 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/microsoft/retina go 1.24.11 require ( - github.com/go-chi/chi/v5 v5.2.3 + github.com/go-chi/chi/v5 v5.2.4 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.23.0 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index 0d2b0c7119..93506c6c06 100644 --- a/go.sum +++ b/go.sum @@ -575,8 +575,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= -github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= +github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= From 59cb07992dac1b37ceaefb14550b732a75bd5bd7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 19:12:25 +0000 Subject: [PATCH 199/448] deps: bump github.com/mdlayher/netlink from 1.7.2 to 1.8.0 (#2010) Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.7.2 to 1.8.0.
Release notes

Sourced from github.com/mdlayher/netlink's releases.

v1.8.0

See https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md#v180.

Changelog

Sourced from github.com/mdlayher/netlink's changelog.

1.8.0

  • [Improvement]: Updated dependencies, test with Go 1.23 to 1.25.
  • [Improvement]: Use Go 1.21's binary.NativeEndian (#220)
  • [Improvement]: Expose socket ReadBuffer & WriteBuffer functions (#223)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/mdlayher/netlink&package-manager=go_modules&previous-version=1.7.2&new-version=1.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 327f4afffc..b796521352 100644 --- a/go.mod +++ b/go.mod @@ -289,7 +289,7 @@ require ( github.com/inspektor-gadget/inspektor-gadget v0.27.0 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 - github.com/mdlayher/netlink v1.7.2 + github.com/mdlayher/netlink v1.8.0 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.0 github.com/onsi/ginkgo/v2 v2.25.3 diff --git a/go.sum b/go.sum index 93506c6c06..c43f0dc542 100644 --- a/go.sum +++ b/go.sum @@ -1069,8 +1069,8 @@ github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuri github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= -github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= -github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/netlink v1.8.0 h1:e7XNIYJKD7hUct3Px04RuIGJbBxy1/c4nX7D5YyvvlM= +github.com/mdlayher/netlink v1.8.0/go.mod h1:UhgKXUlDQhzb09DrCl2GuRNEglHmhYoWAHid9HK3594= github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= From 3c10a9a4e7edc73ad2240098b9171f2418c3cecf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:35:49 -0500 Subject: [PATCH 200/448] deps: bump actions/checkout from 6.0.1 to 6.0.2 (#2002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
Release notes

Sourced from actions/checkout's releases.

v6.0.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v6.0.1...v6.0.2

Commits
  • de0fac2 Fix tag handling: preserve annotations and explicit fetch-tags (#2356)
  • 064fe7f Add orchestration_id to git user-agent when ACTIONS_ORCHESTRATION_ID is set (...
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=6.0.1&new-version=6.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/docs.yaml | 2 +- .github/workflows/e2e-test-event-writer.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 16 ++++++++-------- .github/workflows/kapinger.yaml | 2 +- .github/workflows/markdownlint.yaml | 2 +- .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 14 +++++++------- .github/workflows/release-validation.yaml | 2 +- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- .github/workflows/trivy.yaml | 2 +- .github/workflows/update-hubble.yaml | 2 +- 18 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 64b2bdb112..274fc197ec 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository if: env.IS_NOT_MERGE_GROUP - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go if: env.IS_NOT_MERGE_GROUP uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 3123f4f97e..ec20c37db8 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-node@v6 with: node-version: 20 diff --git a/.github/workflows/e2e-test-event-writer.yml b/.github/workflows/e2e-test-event-writer.yml index 964e5fe6e9..3ec5625c8e 100644 --- a/.github/workflows/e2e-test-event-writer.yml +++ b/.github/workflows/e2e-test-event-writer.yml @@ -31,4 +31,4 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 01ce930bed..806925738d 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -86,7 +86,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index c94481eb03..4d5df60fff 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -20,7 +20,7 @@ jobs: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 487a74a563..c932728484 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Set up Go @@ -35,7 +35,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Set up Go diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 5362aa177b..3bca0a0b54 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -68,7 +68,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -108,7 +108,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries uses: actions/download-artifact@v7 @@ -163,7 +163,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -213,7 +213,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -262,7 +262,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -319,7 +319,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup QEMU uses: docker/setup-qemu-action@v3 @@ -347,7 +347,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 8b8f358db8..964d4df20b 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set outputs id: vars diff --git a/.github/workflows/markdownlint.yaml b/.github/workflows/markdownlint.yaml index 2b42f21532..67a957da3d 100644 --- a/.github/workflows/markdownlint.yaml +++ b/.github/workflows/markdownlint.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: DavidAnson/markdownlint-cli2-action@v9 with: command: config diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index e99e231675..be43fd7d29 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 75b8f366bc..e1daaf6631 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -19,7 +19,7 @@ jobs: if: github.ref_type == 'tag' steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 753674a544..ace61a7a88 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -64,7 +64,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -101,7 +101,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries uses: actions/download-artifact@v7 @@ -149,7 +149,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -194,7 +194,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -237,7 +237,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: @@ -287,7 +287,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index 084f86f807..f4370b4fdc 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get latest tag id: get_latest_tag diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 8bd6369654..954f1f67bf 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -68,7 +68,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index d73a43c05e..fba77a7590 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -15,7 +15,7 @@ jobs: tofu_version: 1.8.3 - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 20840dfc33..05a22804b6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index e170645f0e..6e4b082235 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest # trivy only supports running on Linux steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get Tag run: | diff --git a/.github/workflows/update-hubble.yaml b/.github/workflows/update-hubble.yaml index 1ba1c06bdc..0d4ac4dcfd 100644 --- a/.github/workflows/update-hubble.yaml +++ b/.github/workflows/update-hubble.yaml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest Hubble version id: get_version From e386eaf23bb3711d6b422b7a6a806bfbf84da74f Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Fri, 30 Jan 2026 11:45:44 +0000 Subject: [PATCH 201/448] chore(shell): add bpftrace to shell image (#1694) # Description Add `bpftrace` to retina shell. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Tests executed: ```bash # 1. Build binary with: make retina-shell-image # 2. Push image to registry # 3. Run kubectl retina shell: $ ./artifacts/kubectl-retina shell aks-nodepool1-42816995-vmss000000 --capabilities=NET_ADMIN,SYS_ADMIN,SYS_RESOURCE,BPF,MKNOD,SYS_CHROOT --retina-shell-image-version=v0.0.36-3006-5 --retina-shell-image-repo=ghcr.io/alexcastilio/retina/retina-shell --apparmor-unconfined --seccomp-unconfined --mount-host-filesystem # 4. bpftrace commands executed: root@aks-nodepool1-42816995-vmss000000 [ / ]# bpftrace -e 'kprobe:tcp_v4_rcv { printf("tcp packet received\n"); }' Attaching 1 probe... tcp packet received tcp packet received tcp packet received tcp packet received tcp packet received ^C root@aks-nodepool1-42816995-vmss000000 [ / ]# bpftrace -e 'tracepoint:syscalls:sys_enter_connect { printf("connect\n"); }' Attaching 1 probe... connect connect connect connect connect connect connect connect connect ^C # for this test, open another terminal and run some commands that make dns calls (e.g. curl, wget) root@aks-nodepool1-42816995-vmss000000 [ / ]# bpftrace -e 'uprobe:/usr/lib/libc.so.6:getaddrinfo { @start[tid] = nsecs; } uretprobe:/usr/lib/libc.so.6:getaddrinfo { @latency = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); }' Attaching 2 probes... ^C root@aks-nodepool1-42816995-vmss000000 [ / ]# @latency: [2K, 4K) 1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [4K, 8K) 1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [8K, 16K) 0 | | [16K, 32K) 1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- docs/06-Troubleshooting/shell.md | 28 +++++++++++++++++++++++++++- shell/Dockerfile | 6 +++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/06-Troubleshooting/shell.md b/docs/06-Troubleshooting/shell.md index 3951feb5f2..f0d12f355a 100644 --- a/docs/06-Troubleshooting/shell.md +++ b/docs/06-Troubleshooting/shell.md @@ -4,7 +4,7 @@ The `retina shell` command allows you to start an interactive shell on a Kubernetes node or pod for adhoc debugging. -This runs a container image built from the Dockerfile in the `/shell` directory, with many common networking tools installed (`ping`, `curl`, etc.), as well as specialized tools such as [bpftool](#bpftool), [pwru](#pwru) or [Inspektor Gadget](#inspektor-gadget-ig). +This runs a container image built from the Dockerfile in the `/shell` directory, with many common networking tools installed (`ping`, `curl`, etc.), as well as specialized tools such as [bpftool](#bpftool), [bpftrace](#bpftrace) [pwru](#pwru) or [Inspektor Gadget](#inspektor-gadget-ig). Currently the Retina Shell only works in Linux environments. Windows support will be added in the future. @@ -235,6 +235,32 @@ bpftool prog show bpftool map dump id ``` +## [bpftrace](https://bpftrace.org/) + +bpftrace is a high-level tracing language for Linux and provides a quick and easy way for people to write observability-based eBPF programs. + +Requires the the flags `--mount-host-filesystem`, `--apparmor-unconfined`, `--seccomp-unconfined`, and the following capabilities: + +* `NET_ADMIN` +* `SYS_ADMIN` +* `SYS_RESOURCE` +* `BPF` +* `MKNOD` +* `SYS_CHROOT` + +```sh +# e.g. pod debugging +kubectl retina shell -n kube-system pod/ --capabilities=NET_ADMIN,SYS_ADMIN,SYS_RESOURCE,BPF,MKNOD,SYS_CHROOT --mount-host-filesystem --apparmor-unconfined --seccomp-unconfined +``` + +You can then run for example: + +```shell +bpftrace --help +bpftrace -e 'kprobe:tcp_v4_rcv { printf("tcp packet received\n"); }' +bpftrace -e 'tracepoint:syscalls:sys_enter_connect { printf("connect\n"); }' +``` + ## [Inspektor Gadget (ig)](https://inspektor-gadget.io/) Tools and framework for data collection and system inspection on Kubernetes clusters and Linux hosts using eBPF. diff --git a/shell/Dockerfile b/shell/Dockerfile index 74f1716259..f0ba1541d6 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -28,16 +28,20 @@ RUN tdnf install -y \ tar \ file \ bpftool \ + bpftrace \ ig \ && tdnf clean all -# Create the entrypoint script to mount debugfs +# Create the entrypoint script to mount debugfs and tracefs SHELL ["/bin/bash", "-c"] RUN echo $'#!/bin/bash\n\ if ! mountpoint -q /sys/kernel/debug; then\n\ mount -t debugfs none /sys/kernel/debug\n\ fi\n\ +if ! mountpoint -q /sys/kernel/tracing; then\n\ +mount -t tracefs tracefs /sys/kernel/tracing\n\ +fi\n\ exec "$@"' > /usr/local/bin/entrypoint.sh; # Set the host root directory for IG From 28038c3b7c8f823534f9695ec67a1ef501c789a6 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 5 Feb 2026 14:29:22 -0500 Subject: [PATCH 202/448] fix(ci): use native arm64 runners for shell image build (#2024) # Description Use native arm64 runners (`ubuntu-24.04-arm`) for arm64 shell image builds instead of QEMU emulation on x86_64 runners. The shell image build was getting stuck for 2+ hours when building arm64 images because installing `bpftrace` and its dependencies (LLVM 18.1, clang - 527MB total) under QEMU is extremely slow. The v1.0.3 release workflow has been stuck/retried 15+ times due to this. Changes: - Use native arm64 runners for shell image builds in `images.yaml` and `release-images.yaml` - Skip local export for shell image in Makefile (no artifacts needed, speeds up build) ## Related Issue Unblocks v1.0.3 release ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Tested locally - shell image builds in ~47 seconds without local export. Signed-off-by: Quang Nguyen --- .github/workflows/images.yaml | 16 +++++++++------- .github/workflows/release-images.yaml | 16 +++++++++------- Makefile | 4 +++- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 3bca0a0b54..a509b743e0 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -203,13 +203,18 @@ jobs: IS_MERGE_GROUP: ${{ github.event_name == 'merge_group' }} retina-shell-images: - name: Build Retina Shell Images - runs-on: ubuntu-latest + name: Build Retina Shell Images (${{ matrix.platform }}, ${{ matrix.arch }}) + runs-on: ${{ matrix.runner }} strategy: matrix: - platform: ["linux"] - arch: ["amd64", "arm64"] + include: + - platform: linux + arch: amd64 + runner: ubuntu-latest + - platform: linux + arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -220,9 +225,6 @@ jobs: go-version-file: go.mod - run: go version - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Az CLI login uses: azure/login@v2 if: ${{ github.event_name == 'merge_group' }} diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index ace61a7a88..31c9ccba8b 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -184,13 +184,18 @@ jobs: done retina-shell-images: - name: Build Retina Shell Images - runs-on: ubuntu-latest + name: Build Retina Shell Images (${{ matrix.platform }}, ${{ matrix.arch }}) + runs-on: ${{ matrix.runner }} strategy: matrix: - platform: ["linux"] - arch: ["amd64", "arm64"] + include: + - platform: linux + arch: amd64 + runner: ubuntu-latest + - platform: linux + arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -204,9 +209,6 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v4.0.0 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin diff --git a/Makefile b/Makefile index b29dd3b2b6..20c5d01a6d 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ ifndef TAG endif OUTPUT_DIR = $(REPO_ROOT)/output ARTIFACTS_DIR = $(REPO_ROOT)/artifacts +OUTPUT_LOCAL ?= --output type=local,dest=$(ARTIFACTS_DIR) BUILD_DIR = $(OUTPUT_DIR)/$(GOOS)_$(GOARCH) RETINA_BUILD_DIR = $(BUILD_DIR)/retina RETINA_DIR = $(REPO_ROOT)/controller @@ -234,7 +235,7 @@ container-docker: buildx # util target to build container images using docker bu --build-arg VERSION=$(VERSION) $(EXTRA_BUILD_ARGS) \ --target=$(TARGET) \ -t $(IMAGE_REGISTRY)/$(IMAGE):$(TAG) \ - --output type=local,dest=$(ARTIFACTS_DIR) \ + $(OUTPUT_LOCAL) \ $(BUILDX_ACTION) \ $(CONTEXT_DIR) @@ -325,6 +326,7 @@ retina-shell-image: IMAGE=$(RETINA_SHELL_IMAGE) \ VERSION=$(TAG) \ TAG=$(RETINA_PLATFORM_TAG) \ + OUTPUT_LOCAL= \ CONTEXT_DIR=$(REPO_ROOT) kubectl-retina-image: From 6862bf30eba5f3a190f1e1f21dba942b2ec86861 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:53:53 -0500 Subject: [PATCH 203/448] chore(deps): bump webpack from 5.96.1 to 5.105.0 in /site in the npm_and_yarn group across 1 directory (#2025) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 1 update in the /site directory: [webpack](https://github.com/webpack/webpack). Updates `webpack` from 5.96.1 to 5.105.0
Release notes

Sourced from webpack's releases.

v5.105.0

Minor Changes

  • Allow resolving worker module by export condition name when using new Worker() (by @​hai-x in #20353)

  • Detect conditional imports to avoid compile-time linking errors for non-existent exports. (by @​hai-x in #20320)

  • Added the tsconfig option for the resolver options (replacement for tsconfig-paths-webpack-plugin). Can be false (disabled), true (use the default tsconfig.json file to search for it), a string path to tsconfig.json, or an object with configFile and references options. (by @​alexander-akait in #20400)

  • Support import.defer() for context modules. (by @​ahabhgk in #20399)

  • Added support for array values ​​to the devtool option. (by @​hai-x in #20191)

  • Improve rendering node built-in modules for ECMA module output. (by @​hai-x in #20255)

  • Unknown import.meta properties are now determined at runtime instead of being statically analyzed at compile time. (by @​xiaoxiaojx in #20312)

Patch Changes

  • Fixed ESM default export handling for .mjs files in Module Federation (by @​y-okt in #20189)

  • Optimized import.meta.env handling in destructuring assignments by using cached stringified environment definitions. (by @​xiaoxiaojx in #20313)

  • Respect the stats.errorStack option in stats output. (by @​samarthsinh2660 in #20258)

  • Fixed a bug where declaring a module variable in module scope would conflict with the default moduleArgument. (by @​xiaoxiaojx in #20265)

  • Fix VirtualUrlPlugin to set resourceData.context for proper module resolution. Previously, when context was not set, it would fallback to the virtual scheme path (e.g., virtual:routes), which is not a valid filesystem path, causing subsequent resolve operations to fail. (by @​xiaoxiaojx in #20390)

  • Fixed Worker self-import handling to support various URL patterns (e.g., import.meta.url, new URL(import.meta.url), new URL(import.meta.url, import.meta.url), new URL("./index.js", import.meta.url)). Workers that resolve to the same module are now properly deduplicated, regardless of the URL syntax used. (by @​xiaoxiaojx in #20381)

  • Reuse the same async entrypoint for the same Worker URL within a module to avoid circular dependency warnings when multiple Workers reference the same resource. (by @​xiaoxiaojx in #20345)

  • Fixed a bug where a self-referencing dependency would have an unused export name when imported inside a web worker. (by @​samarthsinh2660 in #20251)

  • Fix missing export generation when concatenated modules in different chunks share the same runtime in module library bundles. (by @​hai-x in #20346)

  • Fixed import.meta.env.xxx behavior: when accessing a non-existent property, it now returns empty object instead of full object at runtime. (by @​xiaoxiaojx in #20289)

  • Improved parsing error reporting by adding a link to the loader documentation. (by @​gaurav10gg in #20244)

  • Fix typescript types. (by @​alexander-akait in #20305)

  • Add declaration for unused harmony import specifier. (by @​hai-x in #20286)

  • Fix compressibility of modules while retaining portability. (by @​dmichon-msft in #20287)

  • Optimize source map generation: only include ignoreList property when it has content, avoiding empty arrays in source maps. (by @​xiaoxiaojx in #20319)

  • Preserve star exports for dependencies in ECMA module output. (by @​hai-x in #20293)

... (truncated)

Changelog

Sourced from webpack's changelog.

5.105.0

Minor Changes

  • Allow resolving worker module by export condition name when using new Worker() (by @​hai-x in #20353)

  • Detect conditional imports to avoid compile-time linking errors for non-existent exports. (by @​hai-x in #20320)

  • Added the tsconfig option for the resolver options (replacement for tsconfig-paths-webpack-plugin). Can be false (disabled), true (use the default tsconfig.json file to search for it), a string path to tsconfig.json, or an object with configFile and references options. (by @​alexander-akait in #20400)

  • Support import.defer() for context modules. (by @​ahabhgk in #20399)

  • Added support for array values ​​to the devtool option. (by @​hai-x in #20191)

  • Improve rendering node built-in modules for ECMA module output. (by @​hai-x in #20255)

  • Unknown import.meta properties are now determined at runtime instead of being statically analyzed at compile time. (by @​xiaoxiaojx in #20312)

Patch Changes

  • Fixed ESM default export handling for .mjs files in Module Federation (by @​y-okt in #20189)

  • Optimized import.meta.env handling in destructuring assignments by using cached stringified environment definitions. (by @​xiaoxiaojx in #20313)

  • Respect the stats.errorStack option in stats output. (by @​samarthsinh2660 in #20258)

  • Fixed a bug where declaring a module variable in module scope would conflict with the default moduleArgument. (by @​xiaoxiaojx in #20265)

  • Fix VirtualUrlPlugin to set resourceData.context for proper module resolution. Previously, when context was not set, it would fallback to the virtual scheme path (e.g., virtual:routes), which is not a valid filesystem path, causing subsequent resolve operations to fail. (by @​xiaoxiaojx in #20390)

  • Fixed Worker self-import handling to support various URL patterns (e.g., import.meta.url, new URL(import.meta.url), new URL(import.meta.url, import.meta.url), new URL("./index.js", import.meta.url)). Workers that resolve to the same module are now properly deduplicated, regardless of the URL syntax used. (by @​xiaoxiaojx in #20381)

  • Reuse the same async entrypoint for the same Worker URL within a module to avoid circular dependency warnings when multiple Workers reference the same resource. (by @​xiaoxiaojx in #20345)

  • Fixed a bug where a self-referencing dependency would have an unused export name when imported inside a web worker. (by @​samarthsinh2660 in #20251)

  • Fix missing export generation when concatenated modules in different chunks share the same runtime in module library bundles. (by @​hai-x in #20346)

  • Fixed import.meta.env.xxx behavior: when accessing a non-existent property, it now returns empty object instead of full object at runtime. (by @​xiaoxiaojx in #20289)

  • Improved parsing error reporting by adding a link to the loader documentation. (by @​gaurav10gg in #20244)

  • Fix typescript types. (by @​alexander-akait in #20305)

  • Add declaration for unused harmony import specifier. (by @​hai-x in #20286)

  • Fix compressibility of modules while retaining portability. (by @​dmichon-msft in #20287)

  • Optimize source map generation: only include ignoreList property when it has content, avoiding empty arrays in source maps. (by @​xiaoxiaojx in #20319)

... (truncated)

Commits
  • 1486f9a chore(release): new release
  • 1a517f6 feat: added the tsconfig option for the resolver options (#20400)
  • 7b3b0f7 feat: support import.defer() for context modules
  • c4a6a92 refactor: more types and increase types coverage
  • 5ecc58d feat: consider asset module as side-effect-free (#20352)
  • cce0f69 test: avoid comma operator in BinaryMiddleware test (#20398)
  • cd4793d feat: support import specifier guard (#20320)
  • fe48655 docs: update examples (#20397)
  • de107f8 fix(VirtualUrlPlugin): set resourceData.context to avoid invalid fallback (#2...
  • a656ab1 test: add self-import test case for dynamic import (#20389)
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by [GitHub Actions](https://www.npmjs.com/~GitHub Actions), a new releaser for webpack since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=webpack&package-manager=npm_and_yarn&previous-version=5.96.1&new-version=5.105.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 450 +++++++++++++++++++---------------------- 1 file changed, 204 insertions(+), 246 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 7e5268d417..0973ab047c 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -5268,9 +5268,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -5598,145 +5598,162 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" }, "node_modules/abbrev": { "version": "1.1.1", @@ -5787,9 +5804,9 @@ } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5798,6 +5815,18 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -6312,9 +6341,9 @@ ] }, "node_modules/baseline-browser-mapping": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.16.tgz", - "integrity": "sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==", + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -6471,9 +6500,9 @@ } }, "node_modules/browserslist": { - "version": "4.26.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", - "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "funding": [ { "type": "opencollective", @@ -6490,11 +6519,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.9", - "caniuse-lite": "^1.0.30001746", - "electron-to-chromium": "^1.5.227", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -6691,9 +6720,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001750", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001750.tgz", - "integrity": "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==", + "version": "1.0.30001768", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001768.tgz", + "integrity": "sha512-qY3aDRZC5nWPgHUgIB84WL+nySuo19wk0VJpp/XI9T34lrvkyhRvNVOFJOp2kxClQhiFBu+TaUSudf6oa3vkSA==", "funding": [ { "type": "opencollective", @@ -8342,9 +8371,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.234", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.234.tgz", - "integrity": "sha512-RXfEp2x+VRYn8jbKfQlRImzoJU01kyDvVPBmG39eU2iuRVhuS6vQNocB8J0/8GrIMLnPzgz4eW6WiRnJkTuNWg==", + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -8394,12 +8423,13 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -8445,9 +8475,10 @@ } }, "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -9433,7 +9464,8 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" }, "node_modules/global-dirs": { "version": "3.0.1", @@ -11013,11 +11045,16 @@ "license": "MIT" }, "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/loader-utils": { @@ -13670,9 +13707,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", - "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "license": "MIT" }, "node_modules/nopt": { @@ -17874,11 +17911,16 @@ } }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tar-fs": { @@ -17906,12 +17948,13 @@ } }, "node_modules/terser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", - "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -17923,15 +17966,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -17955,29 +17999,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -17991,28 +18012,6 @@ "node": ">= 10.13.0" } }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -18505,9 +18504,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "funding": [ { "type": "opencollective", @@ -18820,9 +18819,10 @@ } }, "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -18851,34 +18851,36 @@ } }, "node_modules/webpack": { - "version": "5.96.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "version": "5.105.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", + "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.19.0", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -19113,41 +19115,14 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "node_modules/webpack/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -19167,23 +19142,6 @@ "node": ">= 0.6" } }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/webpackbar": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", From dbe86ddb96a6b1c6aa4b2fc16aad9a0573eaddfe Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Thu, 5 Feb 2026 19:44:49 -0800 Subject: [PATCH 204/448] fix: update CRD manifests to match sources of truth (#2026) # Description These CRD manifest updates were missed in previous PRs, reconcile the drift. ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [X] I have updated the documentation, if necessary. - [X] I have added tests, if applicable. ## Additional Notes These new definitions were added in https://github.com/microsoft/retina/pull/1990 and https://github.com/microsoft/retina/pull/1649 and already include relevant tests. This simply updates the deployed CRDs to match the expected types. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- crd/api/v1alpha1/zz_generated.deepcopy.go | 10 +++++ .../helm/retina/crds/retina.sh_captures.yaml | 41 +++++++++++-------- .../crds/retina.sh_metricsconfigurations.yaml | 2 +- .../crds/retina.sh_retinaendpoints.yaml | 2 +- .../crds/retina.sh_tracesconfigurations.yaml | 2 +- 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/crd/api/v1alpha1/zz_generated.deepcopy.go b/crd/api/v1alpha1/zz_generated.deepcopy.go index 48b9c3bdfb..3229a38b32 100644 --- a/crd/api/v1alpha1/zz_generated.deepcopy.go +++ b/crd/api/v1alpha1/zz_generated.deepcopy.go @@ -138,6 +138,11 @@ func (in *CaptureOption) DeepCopyInto(out *CaptureOption) { *out = new(int) **out = **in } + if in.Interfaces != nil { + in, out := &in.Interfaces, &out.Interfaces + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CaptureOption. @@ -215,6 +220,11 @@ func (in *CaptureTarget) DeepCopyInto(out *CaptureTarget) { *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } + if in.PodNames != nil { + in, out := &in.PodNames, &out.PodNames + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CaptureTarget. diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml index 749d2f3cfb..3eb3f66f9b 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.5 name: captures.retina.sh spec: group: retina.sh @@ -53,6 +53,14 @@ spec: should continue for. pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ type: string + interfaces: + description: |- + Interfaces specifies the network interfaces on which to capture packets. + If specified, captures only on the listed interfaces. + If empty, captures on all interfaces by default. + items: + type: string + type: array maxCaptureSize: default: 100 description: MaxCaptureSize limits the capture file to MB @@ -165,6 +173,14 @@ spec: type: object type: object x-kubernetes-map-type: atomic + podNames: + description: |- + PodNames allows selecting specific pods by their names. + If specified, the capture will be performed on the pods with matching names in the specified namespace. + PodNames is incompatible with NodeSelector, NamespaceSelector, and PodSelector. + items: + type: string + type: array podSelector: description: |- This is a label selector which selects Pods. This field follows standard label @@ -290,10 +306,14 @@ spec: description: SecretName is the name of secret which stores S3 compliant storage access key and secret key. type: string + required: + - bucket + - secretName type: object type: object required: - captureConfiguration + - outputConfiguration type: object status: description: CaptureStatus describes the status of the capture. @@ -310,16 +330,8 @@ spec: type: string conditions: items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -360,12 +372,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml index b0453ebf81..feb3d8956a 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.5 name: metricsconfigurations.retina.sh spec: group: retina.sh diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml index a9b94e5999..f09c04ad0f 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.5 name: retinaendpoints.retina.sh spec: group: retina.sh diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml index ee00af15ae..d1850bfe44 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.5 name: tracesconfigurations.retina.sh spec: group: retina.sh From 1479014d0ad0750f8e85d61ad1517555b7e330cd Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 6 Feb 2026 13:27:06 +0000 Subject: [PATCH 205/448] fix(goreleaser): Generate darwin metadata protos for releases (#2019) # Description - Add darwin metadata proto and generated types so `RetinaMetadata`/`DNSType` compile on darwin targets. - Update proto generation to run per-OS protos and include darwin output. ## Testing - make proto-gen ## Related Issue - Fixes #2018 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- controller/Dockerfile.proto | 4 +- pkg/utils/metadata_darwin.pb.go | 367 ++++++++++++++++++++++++++++++++ pkg/utils/metadata_darwin.proto | 40 ++++ 3 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 pkg/utils/metadata_darwin.pb.go create mode 100644 pkg/utils/metadata_darwin.proto diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index d331466dba..2eca3baa35 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -13,4 +13,6 @@ RUN unzip protoc-24.2-linux-x86_64.zip -d protoc RUN mv protoc/bin/protoc /usr/bin/protoc WORKDIR /app -ENTRYPOINT protoc -I=. --go_out=paths=source_relative:. ./pkg/utils/metadata_linux.proto +ENTRYPOINT /bin/sh -c "protoc -I=. --go_out=paths=source_relative:. ./pkg/utils/metadata_linux.proto && \ + protoc -I=. --go_out=paths=source_relative:. ./pkg/utils/metadata_darwin.proto && \ + protoc -I=. --go_out=paths=source_relative:. ./pkg/utils/metadata_windows.proto" diff --git a/pkg/utils/metadata_darwin.pb.go b/pkg/utils/metadata_darwin.pb.go new file mode 100644 index 0000000000..9775e5881f --- /dev/null +++ b/pkg/utils/metadata_darwin.pb.go @@ -0,0 +1,367 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v4.24.2 +// source: pkg/utils/metadata_darwin.proto + +package utils + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type DNSType int32 + +const ( + DNSType_UNKNOWN DNSType = 0 + DNSType_QUERY DNSType = 1 + DNSType_RESPONSE DNSType = 2 +) + +// Enum value maps for DNSType. +var ( + DNSType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "QUERY", + 2: "RESPONSE", + } + DNSType_value = map[string]int32{ + "UNKNOWN": 0, + "QUERY": 1, + "RESPONSE": 2, + } +) + +func (x DNSType) Enum() *DNSType { + p := new(DNSType) + *p = x + return p +} + +func (x DNSType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DNSType) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_utils_metadata_darwin_proto_enumTypes[0].Descriptor() +} + +func (DNSType) Type() protoreflect.EnumType { + return &file_pkg_utils_metadata_darwin_proto_enumTypes[0] +} + +func (x DNSType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DNSType.Descriptor instead. +func (DNSType) EnumDescriptor() ([]byte, []int) { + return file_pkg_utils_metadata_darwin_proto_rawDescGZIP(), []int{0} +} + +// Ref: pkg/plugin/dropreason/_cprog/drop_reason.h. +type DropReason int32 + +const ( + DropReason_IPTABLE_RULE_DROP DropReason = 0 + DropReason_IPTABLE_NAT_DROP DropReason = 1 + DropReason_TCP_CONNECT_BASIC DropReason = 2 + DropReason_TCP_ACCEPT_BASIC DropReason = 3 + DropReason_TCP_CLOSE_BASIC DropReason = 4 + DropReason_CONNTRACK_ADD_DROP DropReason = 5 + DropReason_UNKNOWN_DROP DropReason = 6 +) + +// Enum value maps for DropReason. +var ( + DropReason_name = map[int32]string{ + 0: "IPTABLE_RULE_DROP", + 1: "IPTABLE_NAT_DROP", + 2: "TCP_CONNECT_BASIC", + 3: "TCP_ACCEPT_BASIC", + 4: "TCP_CLOSE_BASIC", + 5: "CONNTRACK_ADD_DROP", + 6: "UNKNOWN_DROP", + } + DropReason_value = map[string]int32{ + "IPTABLE_RULE_DROP": 0, + "IPTABLE_NAT_DROP": 1, + "TCP_CONNECT_BASIC": 2, + "TCP_ACCEPT_BASIC": 3, + "TCP_CLOSE_BASIC": 4, + "CONNTRACK_ADD_DROP": 5, + "UNKNOWN_DROP": 6, + } +) + +func (x DropReason) Enum() *DropReason { + p := new(DropReason) + *p = x + return p +} + +func (x DropReason) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DropReason) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_utils_metadata_darwin_proto_enumTypes[1].Descriptor() +} + +func (DropReason) Type() protoreflect.EnumType { + return &file_pkg_utils_metadata_darwin_proto_enumTypes[1] +} + +func (x DropReason) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DropReason.Descriptor instead. +func (DropReason) EnumDescriptor() ([]byte, []int) { + return file_pkg_utils_metadata_darwin_proto_rawDescGZIP(), []int{1} +} + +type RetinaMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Bytes uint32 `protobuf:"varint,1,opt,name=bytes,proto3" json:"bytes,omitempty"` + // DNS metadata. + DnsType DNSType `protobuf:"varint,2,opt,name=dns_type,json=dnsType,proto3,enum=utils.DNSType" json:"dns_type,omitempty"` + NumResponses uint32 `protobuf:"varint,3,opt,name=num_responses,json=numResponses,proto3" json:"num_responses,omitempty"` + // TCP ID. Either Tsval or Tsecr will be set. + TcpId uint64 `protobuf:"varint,4,opt,name=tcp_id,json=tcpId,proto3" json:"tcp_id,omitempty"` + // Drop reason in Retina. + DropReason DropReason `protobuf:"varint,5,opt,name=drop_reason,json=dropReason,proto3,enum=utils.DropReason" json:"drop_reason,omitempty"` + // Sampling metadata, for packetparser. + PreviouslyObservedPackets uint32 `protobuf:"varint,6,opt,name=previously_observed_packets,json=previouslyObservedPackets,proto3" json:"previously_observed_packets,omitempty"` + PreviouslyObservedBytes uint32 `protobuf:"varint,7,opt,name=previously_observed_bytes,json=previouslyObservedBytes,proto3" json:"previously_observed_bytes,omitempty"` + PreviouslyObservedTcpFlags map[string]uint32 `protobuf:"bytes,8,rep,name=previously_observed_tcp_flags,json=previouslyObservedTcpFlags,proto3" json:"previously_observed_tcp_flags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *RetinaMetadata) Reset() { + *x = RetinaMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_utils_metadata_darwin_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RetinaMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RetinaMetadata) ProtoMessage() {} + +func (x *RetinaMetadata) ProtoReflect() protoreflect.Message { + mi := &file_pkg_utils_metadata_darwin_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RetinaMetadata.ProtoReflect.Descriptor instead. +func (*RetinaMetadata) Descriptor() ([]byte, []int) { + return file_pkg_utils_metadata_darwin_proto_rawDescGZIP(), []int{0} +} + +func (x *RetinaMetadata) GetBytes() uint32 { + if x != nil { + return x.Bytes + } + return 0 +} + +func (x *RetinaMetadata) GetDnsType() DNSType { + if x != nil { + return x.DnsType + } + return DNSType_UNKNOWN +} + +func (x *RetinaMetadata) GetNumResponses() uint32 { + if x != nil { + return x.NumResponses + } + return 0 +} + +func (x *RetinaMetadata) GetTcpId() uint64 { + if x != nil { + return x.TcpId + } + return 0 +} + +func (x *RetinaMetadata) GetDropReason() DropReason { + if x != nil { + return x.DropReason + } + return DropReason_IPTABLE_RULE_DROP +} + +func (x *RetinaMetadata) GetPreviouslyObservedPackets() uint32 { + if x != nil { + return x.PreviouslyObservedPackets + } + return 0 +} + +func (x *RetinaMetadata) GetPreviouslyObservedBytes() uint32 { + if x != nil { + return x.PreviouslyObservedBytes + } + return 0 +} + +func (x *RetinaMetadata) GetPreviouslyObservedTcpFlags() map[string]uint32 { + if x != nil { + return x.PreviouslyObservedTcpFlags + } + return nil +} + +var File_pkg_utils_metadata_darwin_proto protoreflect.FileDescriptor + +var file_pkg_utils_metadata_darwin_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x5f, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x05, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x22, 0x86, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x74, + 0x69, 0x6e, 0x61, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x12, 0x29, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x44, 0x4e, 0x53, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x73, 0x12, 0x15, 0x0a, 0x06, 0x74, 0x63, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x74, 0x63, 0x70, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x72, 0x6f, 0x70, + 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, + 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x52, 0x0a, 0x64, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x1b, + 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x19, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, 0x62, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, + 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x78, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, + 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, + 0x74, 0x63, 0x70, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x35, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x73, 0x2e, 0x52, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, + 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, + 0x6c, 0x79, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, + 0x67, 0x73, 0x1a, 0x4d, 0x0a, 0x1f, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, + 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x63, 0x70, 0x46, 0x6c, 0x61, 0x67, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x2a, 0x2f, 0x0a, 0x07, 0x44, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, + 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x51, 0x55, 0x45, + 0x52, 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, + 0x10, 0x02, 0x2a, 0xa5, 0x01, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x52, 0x55, 0x4c, + 0x45, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x50, 0x54, 0x41, + 0x42, 0x4c, 0x45, 0x5f, 0x4e, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x15, + 0x0a, 0x11, 0x54, 0x43, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x42, 0x41, + 0x53, 0x49, 0x43, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x5f, 0x41, 0x43, 0x43, + 0x45, 0x50, 0x54, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x54, + 0x43, 0x50, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x04, + 0x12, 0x16, 0x0a, 0x12, 0x43, 0x4f, 0x4e, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x4b, 0x5f, 0x41, 0x44, + 0x44, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x06, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x2f, 0x72, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x74, + 0x69, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_utils_metadata_darwin_proto_rawDescOnce sync.Once + file_pkg_utils_metadata_darwin_proto_rawDescData = file_pkg_utils_metadata_darwin_proto_rawDesc +) + +func file_pkg_utils_metadata_darwin_proto_rawDescGZIP() []byte { + file_pkg_utils_metadata_darwin_proto_rawDescOnce.Do(func() { + file_pkg_utils_metadata_darwin_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_utils_metadata_darwin_proto_rawDescData) + }) + return file_pkg_utils_metadata_darwin_proto_rawDescData +} + +var file_pkg_utils_metadata_darwin_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_pkg_utils_metadata_darwin_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_pkg_utils_metadata_darwin_proto_goTypes = []any{ + (DNSType)(0), // 0: utils.DNSType + (DropReason)(0), // 1: utils.DropReason + (*RetinaMetadata)(nil), // 2: utils.RetinaMetadata + nil, // 3: utils.RetinaMetadata.PreviouslyObservedTcpFlagsEntry +} +var file_pkg_utils_metadata_darwin_proto_depIdxs = []int32{ + 0, // 0: utils.RetinaMetadata.dns_type:type_name -> utils.DNSType + 1, // 1: utils.RetinaMetadata.drop_reason:type_name -> utils.DropReason + 3, // 2: utils.RetinaMetadata.previously_observed_tcp_flags:type_name -> utils.RetinaMetadata.PreviouslyObservedTcpFlagsEntry + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_pkg_utils_metadata_darwin_proto_init() } +func file_pkg_utils_metadata_darwin_proto_init() { + if File_pkg_utils_metadata_darwin_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_utils_metadata_darwin_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*RetinaMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_utils_metadata_darwin_proto_rawDesc, + NumEnums: 2, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_utils_metadata_darwin_proto_goTypes, + DependencyIndexes: file_pkg_utils_metadata_darwin_proto_depIdxs, + EnumInfos: file_pkg_utils_metadata_darwin_proto_enumTypes, + MessageInfos: file_pkg_utils_metadata_darwin_proto_msgTypes, + }.Build() + File_pkg_utils_metadata_darwin_proto = out.File + file_pkg_utils_metadata_darwin_proto_rawDesc = nil + file_pkg_utils_metadata_darwin_proto_goTypes = nil + file_pkg_utils_metadata_darwin_proto_depIdxs = nil +} diff --git a/pkg/utils/metadata_darwin.proto b/pkg/utils/metadata_darwin.proto new file mode 100644 index 0000000000..9e939bccd1 --- /dev/null +++ b/pkg/utils/metadata_darwin.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package utils; + +option go_package = "github.com/microsoft/retina/pkg/utils"; + +message RetinaMetadata { + uint32 bytes = 1; + + // DNS metadata. + DNSType dns_type = 2; + uint32 num_responses = 3; + + // TCP ID. Either Tsval or Tsecr will be set. + uint64 tcp_id = 4; + + // Drop reason in Retina. + DropReason drop_reason = 5; + + // Sampling metadata, for packetparser. + uint32 previously_observed_packets = 6; + uint32 previously_observed_bytes = 7; + map previously_observed_tcp_flags = 8; +} + +enum DNSType { + UNKNOWN = 0; + QUERY = 1; + RESPONSE = 2; +} + +// Ref: pkg/plugin/dropreason/_cprog/drop_reason.h. +enum DropReason { + IPTABLE_RULE_DROP = 0; + IPTABLE_NAT_DROP = 1; + TCP_CONNECT_BASIC = 2; + TCP_ACCEPT_BASIC = 3; + TCP_CLOSE_BASIC = 4; + CONNTRACK_ADD_DROP = 5; + UNKNOWN_DROP = 6; +} From 6b7cec70d8804568bcf917e41070cafaef025a95 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 6 Feb 2026 16:10:44 +0000 Subject: [PATCH 206/448] fix: Add darwin drop reason mapping for GoReleaser builds (#2028) # Description - Add darwin implementation of `GetDropReasonDesc` to fix GoReleaser darwin builds. ## Context - GoReleaser builds darwin targets; utils package lacked darwin implementation, causing undefined symbol. ## Testing - Not run (build-only change). ## Related Issue See issue in this job run (for an unrelated PR) https://github.com/microsoft/retina/actions/runs/21755953385/job/62766139385?pr=1981 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/utils/utils_darwin.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 pkg/utils/utils_darwin.go diff --git a/pkg/utils/utils_darwin.go b/pkg/utils/utils_darwin.go new file mode 100644 index 0000000000..f4dd60ae27 --- /dev/null +++ b/pkg/utils/utils_darwin.go @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +package utils + +import ( + "github.com/cilium/cilium/api/v1/flow" +) + +func GetDropReasonDesc(dr DropReason) flow.DropReason { + // Keep mapping aligned with Linux where drop reasons overlap. + switch dr { //nolint:exhaustive // We are handling all the cases. + case DropReason_IPTABLE_RULE_DROP: + return flow.DropReason_POLICY_DENIED + case DropReason_IPTABLE_NAT_DROP: + return flow.DropReason_SNAT_NO_MAP_FOUND + case DropReason_CONNTRACK_ADD_DROP: + return flow.DropReason_UNKNOWN_CONNECTION_TRACKING_STATE + default: + return flow.DropReason_DROP_REASON_UNKNOWN + } +} From e732a637d6d066966508ec83fe4585b5aef60e8d Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 12 Feb 2026 13:26:33 -0500 Subject: [PATCH 207/448] fix: resolve flaky cache tests and ciliumeventobserver 600s timeout (#2048) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fix unit test reliability issues causing CI flakiness, silent 600-second timeouts, and test-image build failures. ## cache_test.go — Flaky gomock race condition (~50% failure rate) `cache.publish()` fires `Publish` calls in goroutines. Tests used `time.Sleep(1ms)` to wait for completion, but this was a race condition — `ctrl.Finish()` often ran before the goroutines completed, causing "missing call(s) to Publish" errors. **Fix:** Replace `time.Sleep` with `sync.WaitGroup` + gomock `.Do()` callbacks to properly synchronize with async publishes. ## ciliumeventobserver — 600s timeout on every CI run (issue #1688) The `ciliumeventobserver` test package timed out at 600 seconds on every single CI run, silently reporting as green. Multiple bugs contributed: 1. **`monitorLoop` select/default antipattern**: Used `select { case <-ctx.Done(): ... default: DecodeBinary() }` where the blocking `DecodeBinary` call prevented context cancellation from ever being checked. Replaced with a direct blocking read followed by `ctx.Err()` check after errors. 2. **Goroutine leaks in tests**: Tests never closed `net.Pipe` connections, so `monitorLoop` goroutines remained stuck in blocking reads after tests completed, causing the test process to hang until the 10-minute Go test timeout. 3. **Invalid test payload**: `getPayload()` called `CreateL3L4Payload` without Ethernet/IP/TCP layers, causing the Hubble parser to fail with "Ethernet packet too small". Events never reached the external channel, so tests blocked forever on channel reads. 4. **Missing test config**: `TestStart` didn't set `retryDelay`, defaulting to 12 seconds in `connect()`. 5. **Unbuffered channel race**: `externalChannel` was unbuffered, causing a race with the non-blocking send in `parserLoop`. Events were silently dropped, hitting an uninitialized metrics counter (nil pointer panic). ## setup-envtest — GCS 401 Unauthorized breaking test-image CI The `setup-envtest` tool pinned at `v0.0.0-20211110210527-619e6b92dab9` (Nov 2021) downloads etcd/kube-apiserver binaries from a GCS bucket using unauthenticated access. GCS recently started returning `401 Unauthorized`, causing `KUBEBUILDER_ASSETS=""` and failing the `TestAPIs` envtest-based test in `pkg/controllers/daemon/retinaendpoint`. **Fix:** Update `setup-envtest` to `v0.0.0-20250517180713-32e5e9e948a5` (release-0.20 branch), which uses GitHub-based downloads instead of deprecated GCS. ## Lint fixes - Fixed `nilerr` lint: `monitorLoop` checked `ctx.Err() != nil` but returned `nil` — now returns `ctx.Err()`. - Fixed `errcheck` lint: unchecked return value of `tcp.SetNetworkLayerForChecksum` in test. ## Related Issue Fixes #1688 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Testing Completed - `cache_test.go`: Ran 50 iterations (`-count=50`), all 400 test executions pass with 0 failures. - `ciliumeventobserver`: Ran 5 iterations (`-count=5`) with 30s timeout. All 20 tests pass in ~5 seconds total (previously timed out at 600s). - `setup-envtest`: Verified locally that updated version successfully downloads binaries via GitHub (no more GCS 401). ## Additional Notes The `monitorLoop` production code change (removing the `select/default` antipattern) is necessary because the old pattern made it impossible to cancel the monitor loop when `DecodeBinary` was blocking. In production, `Stop()` closes the connection which unblocks the read, and the new `ctx.Err()` check ensures clean shutdown. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- go.mod | 4 +- go.sum | 16 +---- pkg/controllers/cache/cache_test.go | 62 ++++++++++++------- .../ciliumeventobserver_linux.go | 31 +++++----- .../ciliumeventobserver_linux_test.go | 45 ++++++++++++-- 5 files changed, 97 insertions(+), 61 deletions(-) diff --git a/go.mod b/go.mod index b796521352..d49a339a6f 100644 --- a/go.mod +++ b/go.mod @@ -285,6 +285,7 @@ require ( github.com/florianl/go-tc v0.4.5 github.com/go-logr/zapr v1.3.0 github.com/google/gopacket v1.1.19 + github.com/gopacket/gopacket v1.3.1 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/inspektor-gadget/inspektor-gadget v0.27.0 github.com/jellydator/ttlcache/v3 v3.4.0 @@ -481,7 +482,6 @@ require ( github.com/google/wire v0.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect - github.com/gopacket/gopacket v1.3.1 // indirect github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/goreleaser/chglog v0.6.1 // indirect github.com/goreleaser/fileglob v1.3.0 // indirect @@ -659,7 +659,7 @@ require ( lukechampine.com/blake3 v1.2.1 // indirect mvdan.cc/gofumpt v0.7.0 // indirect mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect - sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20211110210527-619e6b92dab9 // indirect + sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5 // indirect sigs.k8s.io/controller-tools v0.16.5 // indirect sigs.k8s.io/gateway-api v1.2.1-0.20250319040149-e8b8afabf889 // indirect sigs.k8s.io/kind v0.23.0 // indirect diff --git a/go.sum b/go.sum index c43f0dc542..db2ec919d6 100644 --- a/go.sum +++ b/go.sum @@ -600,13 +600,11 @@ github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 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-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= @@ -976,7 +974,6 @@ github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1182,7 +1179,6 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw= @@ -1190,7 +1186,6 @@ github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1234,7 +1229,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE 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/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1368,7 +1362,6 @@ github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCp github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= @@ -1584,7 +1577,6 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -1598,7 +1590,6 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1614,7 +1605,6 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= @@ -1682,7 +1672,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1818,7 +1807,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= @@ -1985,8 +1973,8 @@ sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPk sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= -sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20211110210527-619e6b92dab9 h1:ylYUI5uaq/guUFerFRVG81FHSA5/3+fERCE1RQbQUZ4= -sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20211110210527-619e6b92dab9/go.mod h1:+sJcI1F0QI0Cv+8fp5rH5B2fK1LxzrAQqYnaPx9nY8I= +sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5 h1:eOG9vIdpeOc/NI5RStnrYrEL4Crf66SHtfpVXwvRaNc= +sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5/go.mod h1:Cq9jUhwSYol5tNB0O/1vLYxNV9KqnhpvEa6HvJ1w0wY= sigs.k8s.io/controller-tools v0.16.5 h1:5k9FNRqziBPwqr17AMEPPV/En39ZBplLAdOwwQHruP4= sigs.k8s.io/controller-tools v0.16.5/go.mod h1:8vztuRVzs8IuuJqKqbXCSlXcw+lkAv/M2sTpg55qjMY= sigs.k8s.io/gateway-api v1.2.1-0.20250319040149-e8b8afabf889 h1:oCrmvARaph9Rzu+8QWnmKAjgyRqwmZ2J6llfYto8IR8= diff --git a/pkg/controllers/cache/cache_test.go b/pkg/controllers/cache/cache_test.go index 95266d51f7..4ba36eea87 100644 --- a/pkg/controllers/cache/cache_test.go +++ b/pkg/controllers/cache/cache_test.go @@ -4,8 +4,8 @@ package cache import ( "net" + "sync" "testing" - "time" "github.com/microsoft/retina/pkg/common" "github.com/microsoft/retina/pkg/log" @@ -14,10 +14,6 @@ import ( gomock "go.uber.org/mock/gomock" ) -const ( - until = 1 * time.Millisecond -) - func TestNewCache(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) ctrl := gomock.NewController(t) @@ -33,7 +29,11 @@ func TestCacheEndpoints(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() p := pubsub.NewMockPubSubInterface(ctrl) - p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(2) + var wg sync.WaitGroup + wg.Add(2) + p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(2).Do(func(pubsub.PubSubTopic, interface{}) { + wg.Done() + }) p.EXPECT().Subscribe(common.PubSubAPIServer, gomock.Any()).Times(1) c := New(p) assert.NotNil(t, c) @@ -92,7 +92,7 @@ func TestCacheEndpoints(t *testing.T) { err = c.DeleteRetinaEndpoint(addEndpoints.Key()) assert.NoError(t, err) - time.Sleep(until) + wg.Wait() } func TestCacheServices(t *testing.T) { @@ -106,7 +106,11 @@ func TestCacheServices(t *testing.T) { addSvc := common.NewRetinaSvc("svc1", "ns1", nil, nil, nil) - p.EXPECT().Publish(gomock.Any(), gomock.Any()).Times(2) + var wg sync.WaitGroup + wg.Add(2) + p.EXPECT().Publish(gomock.Any(), gomock.Any()).Times(2).Do(func(pubsub.PubSubTopic, interface{}) { + wg.Done() + }) err := c.UpdateRetinaSvc(addSvc) assert.Error(t, err) @@ -136,7 +140,7 @@ func TestCacheServices(t *testing.T) { err = c.DeleteRetinaSvc(addSvc.Key()) assert.NoError(t, err) - time.Sleep(until) + wg.Wait() } func TestCacheNodes(t *testing.T) { @@ -150,7 +154,11 @@ func TestCacheNodes(t *testing.T) { addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4)) - p.EXPECT().Publish(gomock.Any(), gomock.Any()).Times(2) + var wg sync.WaitGroup + wg.Add(2) + p.EXPECT().Publish(gomock.Any(), gomock.Any()).Times(2).Do(func(pubsub.PubSubTopic, interface{}) { + wg.Done() + }) err := c.UpdateRetinaNode(addNode) assert.NoError(t, err) @@ -169,7 +177,7 @@ func TestCacheNodes(t *testing.T) { err = c.DeleteRetinaNode(addNode.Name()) assert.NoError(t, err) - time.Sleep(until) + wg.Wait() } func TestAddPodSvcNodeSameIP(t *testing.T) { @@ -177,9 +185,12 @@ func TestAddPodSvcNodeSameIP(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() p := pubsub.NewMockPubSubInterface(ctrl) - p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(2) - p.EXPECT().Publish(common.PubSubSvc, gomock.Any()).Times(2) - p.EXPECT().Publish(common.PubSubNode, gomock.Any()).Times(1) + var wg sync.WaitGroup + wg.Add(5) // 2 pod + 2 svc + 1 node publishes + doFn := func(pubsub.PubSubTopic, interface{}) { wg.Done() } + p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(2).Do(doFn) + p.EXPECT().Publish(common.PubSubSvc, gomock.Any()).Times(2).Do(doFn) + p.EXPECT().Publish(common.PubSubNode, gomock.Any()).Times(1).Do(doFn) p.EXPECT().Subscribe(common.PubSubAPIServer, gomock.Any()).Times(1) c := New(p) assert.NotNil(t, c) @@ -221,7 +232,7 @@ func TestAddPodSvcNodeSameIP(t *testing.T) { assert.Equal(t, addNode.Name(), node.Name()) assert.Equal(t, addNode.IPString(), node.IPString()) - time.Sleep(until) + wg.Wait() } func TestAddPodSvcNodeSameIPDiffNS(t *testing.T) { @@ -229,9 +240,12 @@ func TestAddPodSvcNodeSameIPDiffNS(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() p := pubsub.NewMockPubSubInterface(ctrl) - p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(2) - p.EXPECT().Publish(common.PubSubSvc, gomock.Any()).Times(2) - p.EXPECT().Publish(common.PubSubNode, gomock.Any()).Times(1) + var wg sync.WaitGroup + wg.Add(5) // 2 pod + 2 svc + 1 node publishes + doFn := func(pubsub.PubSubTopic, interface{}) { wg.Done() } + p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(2).Do(doFn) + p.EXPECT().Publish(common.PubSubSvc, gomock.Any()).Times(2).Do(doFn) + p.EXPECT().Publish(common.PubSubNode, gomock.Any()).Times(1).Do(doFn) p.EXPECT().Subscribe(common.PubSubAPIServer, gomock.Any()).Times(1) c := New(p) assert.NotNil(t, c) @@ -274,7 +288,7 @@ func TestAddPodSvcNodeSameIPDiffNS(t *testing.T) { assert.Equal(t, addNode.Name(), node.Name()) assert.Equal(t, addNode.IPString(), node.IPString()) - time.Sleep(until) + wg.Wait() } func TestAddPodDiffNs(t *testing.T) { @@ -282,7 +296,11 @@ func TestAddPodDiffNs(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() p := pubsub.NewMockPubSubInterface(ctrl) - p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(3) + var wg sync.WaitGroup + wg.Add(3) + p.EXPECT().Publish(common.PubSubPods, gomock.Any()).Times(3).Do(func(pubsub.PubSubTopic, interface{}) { + wg.Done() + }) p.EXPECT().Subscribe(common.PubSubAPIServer, gomock.Any()).Times(1) c := New(p) assert.NotNil(t, c) @@ -318,7 +336,7 @@ func TestAddPodDiffNs(t *testing.T) { assert.Equal(t, addEndpoints.Name(), ep.Name()) assert.Equal(t, addEndpoints.Namespace(), ep.Namespace()) - time.Sleep(until) + wg.Wait() } func TestFailDelete(t *testing.T) { @@ -344,8 +362,6 @@ func TestFailDelete(t *testing.T) { err = c.DeleteRetinaNode(node.Name()) assert.Error(t, err) - - time.Sleep(until) } func TestCachingNamespace(t *testing.T) { diff --git a/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux.go b/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux.go index 5373e5c4fd..324c697e08 100644 --- a/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux.go +++ b/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux.go @@ -156,24 +156,23 @@ func (c *ciliumeventobserver) monitorLoop(ctx context.Context) error { decoder := gob.NewDecoder(c.connection) for { var pl payload.Payload - select { - case <-ctx.Done(): // cancelled or done - c.l.Info("Context done, exiting monitor loop") - return nil - default: - if err := pl.DecodeBinary(decoder); err != nil { - if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { - return err //nolint:wrapcheck // Error is handled by the caller - } - c.l.Warn("Failed to decode payload from cilium", zap.Error(err)) - metrics.LostEventsCounter.WithLabelValues(parserMetric, name).Inc() - continue + if err := pl.DecodeBinary(decoder); err != nil { + // Check if context was cancelled (e.g. connection closed during shutdown). + if ctx.Err() != nil { + c.l.Info("Context done, exiting monitor loop") + return ctx.Err() //nolint:wrapcheck // no additional context needed } - select { - case c.payloadEvents <- &pl: - default: - metrics.LostEventsCounter.WithLabelValues(utils.BufferedChannel, name).Inc() + if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { + return err //nolint:wrapcheck // Error is handled by the caller } + c.l.Warn("Failed to decode payload from cilium", zap.Error(err)) + metrics.LostEventsCounter.WithLabelValues(parserMetric, name).Inc() + continue + } + select { + case c.payloadEvents <- &pl: + default: + metrics.LostEventsCounter.WithLabelValues(utils.BufferedChannel, name).Inc() } } } diff --git a/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go b/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go index 92eec5ce1f..ec0dc6c1e2 100644 --- a/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go +++ b/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go @@ -13,6 +13,7 @@ import ( "github.com/cilium/cilium/pkg/monitor" monitorAPI "github.com/cilium/cilium/pkg/monitor/api" "github.com/cilium/cilium/pkg/monitor/payload" + "github.com/gopacket/gopacket/layers" "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/controllers/cache" "github.com/microsoft/retina/pkg/enricher" @@ -46,19 +47,20 @@ func TestStartError(t *testing.T) { func TestStart(t *testing.T) { ctxWithCancel, cancel := context.WithCancel(context.Background()) - defer cancel() _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) cfg := &config.Config{ EnablePodLevel: true, } cil := New(cfg) - exChan := make(chan *v1.Event) + exChan := make(chan *v1.Event, 1) _ = cil.SetupChannel(exChan) _ = cil.Init() md := NewMockDialer(false) cil.(*ciliumeventobserver).d = md cil.(*ciliumeventobserver).connection = md.reader + cil.(*ciliumeventobserver).retryDelay = 1 * time.Millisecond + cil.(*ciliumeventobserver).maxAttempts = 1 go cil.Start(ctxWithCancel) //nolint:errcheck // do not need for test pl := getPayload() @@ -66,6 +68,11 @@ func TestStart(t *testing.T) { _, _ = md.writer.Write(msg) event := <-exChan assert.Assert(t, event != nil) + + // Clean up: cancel context then close pipe to unblock monitorLoop. + cancel() + md.reader.Close() + md.writer.Close() } func TestMonitorLoop(t *testing.T) { @@ -92,19 +99,22 @@ func TestMonitorLoop(t *testing.T) { time.Sleep(2 * time.Second) plEvent := <-cil.(*ciliumeventobserver).payloadEvents assert.Assert(t, plEvent != nil) + + // Clean up: cancel context then close pipe to unblock monitorLoop. cancel() + md.reader.Close() + md.writer.Close() } func TestParse(t *testing.T) { ctxWithCancel, cancel := context.WithCancel(context.Background()) - defer cancel() _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) cfg := &config.Config{ EnablePodLevel: true, } cil := New(cfg) _ = cil.Init() - exChannel := make(chan *v1.Event) + exChannel := make(chan *v1.Event, 1) _ = cil.SetupChannel(exChannel) cil.(*ciliumeventobserver).retryDelay = 1 * time.Millisecond cil.(*ciliumeventobserver).maxAttempts = 1 @@ -123,6 +133,11 @@ func TestParse(t *testing.T) { assert.Assert(t, len(cil.(*ciliumeventobserver).payloadEvents) == 0) event := <-exChannel assert.Assert(t, event != nil) + + // Clean up: cancel context then close pipe to unblock monitorLoop. + cancel() + md.reader.Close() + md.writer.Close() } func getPayload() payload.Payload { @@ -131,12 +146,30 @@ func getPayload() payload.Payload { SubType: uint8(130), } - data, _ := testutils.CreateL3L4Payload(dn) + eth := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{1, 2, 3, 4, 5, 6}, + DstMAC: net.HardwareAddr{6, 5, 4, 3, 2, 1}, + EthernetType: layers.EthernetTypeIPv4, + } + ip := &layers.IPv4{ + SrcIP: net.IP{1, 2, 3, 4}, + DstIP: net.IP{5, 6, 7, 8}, + Version: 4, + Protocol: layers.IPProtocolTCP, + TTL: 64, + } + tcp := &layers.TCP{ + SrcPort: 12345, + DstPort: 80, + } + _ = tcp.SetNetworkLayerForChecksum(ip) + + data, _ := testutils.CreateL3L4Payload(dn, eth, ip, tcp) pl := payload.Payload{ Data: data, CPU: 0, Lost: 0, - Type: 9, + Type: payload.EventSample, } return pl } From 6f8096c8fa6d5817413fa8716cb2044296018388 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 12 Feb 2026 14:24:03 -0500 Subject: [PATCH 208/448] feat(utils): use structpb.Struct directly for flow extensions (#2015) # Description Replace `RetinaMetadata` with `structpb.Struct` for flow extensions to enable Hubble CLI JSON marshaling without type registration Changes: - Add `NewExtensions()` and `SetExtensions()` helper functions - Update Add* functions to take `*structpb.Struct` instead of `*RetinaMetadata` - Update accessor functions to read from Struct - Update all plugins and tests to use new API ## Related Issue Closes https://github.com/microsoft/retina/issues/1080 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ```bash {"flow":{"time":"2026-01-31T17:10:38.030385093Z","verdict":"FORWARDED","IP":{"source":"10.10.0.5","destination":"192.168.0.73","ipVersion":"IPv4"},"l4":{"TCP":{"source_port":4244,"destination_port":38112,"flags":{"SYN":true,"ACK":true}}},"source":{"ID":1,"identity":1,"labels":["reserved:host"]},"destination":{"ID":51516,"identity":51516,"namespace":"kube-system","labels":["k8s:io.cilium.k8s.namespace.labels.kubernetes.azure.com/managedby=aks","k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system","k8s:io.cilium.k8s.policy.cluster=default","k8s:k8s-app=hubble-relay","k8s:io.cilium.k8s.namespace.labels.addonmanager.kubernetes.io/mode=Reconcile","k8s:io.cilium.k8s.namespace.labels.control-plane=true","k8s:io.cilium.k8s.namespace.labels.kubernetes.io/cluster-service=true","k8s:io.cilium.k8s.policy.serviceaccount=hubble-relay","k8s:io.kubernetes.pod.namespace=kube-system","k8s:pod-template-hash=6b7c54d9ff","k8s:app.kubernetes.io/name=hubble-relay","k8s:app.kubernetes.io/part-of=cilium"],"pod_name":"hubble-relay-6b7c54d9ff-2lsqj"},"Type":"L3_L4","event_type":{"type":4},"traffic_direction":"EGRESS","trace_observation_point":"TO_ENDPOINT","is_reply":true,"Summary":"TCP Flags: SYN:true ACK:true","extensions":{"@type":"type.googleapis.com/google.protobuf.Struct","value":{"bytes":74,"previously_observed_tcp_flags":{"ACK":0,"CWR":0,"ECE":0,"FIN":0,"NS":0,"PSH":0,"RST":0,"SYN":0,"URG":0}}}},"time":"2026-01-31T17:10:38.030385093Z"} {"flow":{"time":"2026-01-31T17:10:38.030403862Z","verdict":"FORWARDED","IP":{"source":"192.168.0.73","destination":"10.10.0.5","ipVersion":"IPv4"},"l4":{"TCP":{"source_port":38112,"destination_port":4244,"flags":{"ACK":true}}},"source":{"ID":51516,"identity":51516,"namespace":"kube-system","labels":["k8s:io.cilium.k8s.namespace.labels.kubernetes.azure.com/managedby=aks","k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system","k8s:io.cilium.k8s.policy.cluster=default","k8s:k8s-app=hubble-relay","k8s:io.cilium.k8s.namespace.labels.addonmanager.kubernetes.io/mode=Reconcile","k8s:io.cilium.k8s.namespace.labels.control-plane=true","k8s:io.cilium.k8s.namespace.labels.kubernetes.io/cluster-service=true","k8s:io.cilium.k8s.policy.serviceaccount=hubble-relay","k8s:io.kubernetes.pod.namespace=kube-system","k8s:pod-template-hash=6b7c54d9ff","k8s:app.kubernetes.io/name=hubble-relay","k8s:app.kubernetes.io/part-of=cilium"],"pod_name":"hubble-relay-6b7c54d9ff-2lsqj"},"destination":{"ID":1,"identity":1,"labels":["reserved:host"]},"Type":"L3_L4","event_type":{"type":4,"sub_type":3},"traffic_direction":"EGRESS","trace_observation_point":"TO_STACK","is_reply":false,"Summary":"TCP Flags: ACK:true","extensions":{"@type":"type.googleapis.com/google.protobuf.Struct","value":{"bytes":66,"previously_observed_tcp_flags":{"ACK":0,"CWR":0,"ECE":0,"FIN":0,"NS":0,"PSH":0,"RST":0,"SYN":0,"URG":0}}}},"time":"2026-01-31T17:10:38.030403862Z"} {"flow":{"time":"2026-01-31T17:10:38.030513168Z","verdict":"DROPPED","IP":{"source":"0.0.0.0","destination":"0.0.0.0","ipVersion":"IPv4"},"source":{"ID":2,"identity":2,"labels":["reserved:world"]},"destination":{"ID":2,"identity":2,"labels":["reserved:world"]},"Type":"L3_L4","event_type":{"type":1},"traffic_direction":"INGRESS","trace_observation_point":"FROM_NETWORK","Summary":"Drop Reason: TCP_ACCEPT_BASIC\nNote: This reason is most accurate. Prefer over others while using Hubble CLI.","extensions":{"@type":"type.googleapis.com/google.protobuf.Struct","value":{"drop_reason":"TCP_ACCEPT_BASIC"}}},"time":"2026-01-31T17:10:38.030513168Z"} {"flow":{"time":"2026-01-31T17:10:38.030525215Z","verdict":"FORWARDED","IP":{"source":"192.168.0.73","destination":"10.10.0.5","ipVersion":"IPv4"},"l4":{"TCP":{"source_port":38112,"destination_port":4244,"flags":{"PSH":true,"ACK":true}}},"source":{"ID":51516,"identity":51516,"namespace":"kube-system","labels":["k8s:io.cilium.k8s.namespace.labels.kubernetes.azure.com/managedby=aks","k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system","k8s:io.cilium.k8s.policy.cluster=default","k8s:k8s-app=hubble-relay","k8s:io.cilium.k8s.namespace.labels.addonmanager.kubernetes.io/mode=Reconcile","k8s:io.cilium.k8s.namespace.labels.control-plane=true","k8s:io.cilium.k8s.namespace.labels.kubernetes.io/cluster-service=true","k8s:io.cilium.k8s.policy.serviceaccount=hubble-relay","k8s:io.kubernetes.pod.namespace=kube-system","k8s:pod-template-hash=6b7c54d9ff","k8s:app.kubernetes.io/name=hubble-relay","k8s:app.kubernetes.io/part-of=cilium"],"pod_name":"hubble-relay-6b7c54d9ff-2lsqj"},"destination":{"ID":1,"identity":1,"labels":["reserved:host"]},"Type":"L3_L4","event_type":{"type":4,"sub_type":3},"traffic_direction":"EGRESS","trace_observation_point":"TO_STACK","is_reply":false,"Summary":"TCP Flags: PSH:true ACK:true","extensions":{"@type":"type.googleapis.com/google.protobuf.Struct","value":{"bytes":90,"previously_observed_tcp_flags":{"ACK":0,"CWR":0,"ECE":0,"FIN":0,"NS":0,"PSH":0,"RST":0,"SYN":0,"URG":0}}}},"time":"2026-01-31T17:10:38.030525215Z"} ``` image ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- pkg/module/metrics/dns.go | 9 +- pkg/module/metrics/dns_test.go | 36 +-- pkg/module/metrics/latency_test.go | 12 +- pkg/plugin/dns/dns_linux.go | 8 +- pkg/plugin/dropreason/dropreason_linux.go | 14 +- pkg/plugin/packetparser/packetparser_linux.go | 22 +- pkg/utils/flow_utils.go | 232 ++++++++++++------ pkg/utils/utils_linux_test.go | 21 +- 8 files changed, 215 insertions(+), 139 deletions(-) diff --git a/pkg/module/metrics/dns.go b/pkg/module/metrics/dns.go index 003d14cb3d..eaf7eb4428 100644 --- a/pkg/module/metrics/dns.go +++ b/pkg/module/metrics/dns.go @@ -141,18 +141,15 @@ func (d *DNSMetrics) responseValues(flow *v1.Flow) []string { func (d *DNSMetrics) getLabelsForProcessFlow(flow *v1.Flow) ([]string, error) { var labels []string // Get the DNS query type - meta := utils.RetinaMetadata{} - if err := flow.GetExtensions().UnmarshalTo(&meta); err != nil { - return labels, errors.Wrapf(err, "failed to unmarshal flow extensions") - } - switch meta.GetDnsType() { + _, dnsType, _ := utils.GetDNS(flow) + switch dnsType { case utils.DNSType_QUERY: labels = d.requestValues(flow) case utils.DNSType_RESPONSE: labels = d.responseValues(flow) case utils.DNSType_UNKNOWN: default: - return labels, errors.Errorf("invalid DNS type %d", int32(meta.GetDnsType())) + return labels, errors.Errorf("invalid DNS type %d", int32(dnsType)) } return labels, nil } diff --git a/pkg/module/metrics/dns_test.go b/pkg/module/metrics/dns_test.go index 7e15fedf4a..55dd833950 100644 --- a/pkg/module/metrics/dns_test.go +++ b/pkg/module/metrics/dns_test.go @@ -94,19 +94,19 @@ func TestGetLabels(t *testing.T) { func TestValues(t *testing.T) { testR := &flow.Flow{} - metaR := &utils.RetinaMetadata{} - utils.AddDNSInfo(testR, metaR, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.AddRetinaMetadata(testR, metaR) + extR := utils.NewExtensions() + utils.AddDNSInfo(testR, extR, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) + utils.SetExtensions(testR, extR) testQ := &flow.Flow{} - metaQ := &utils.RetinaMetadata{} - utils.AddDNSInfo(testQ, metaQ, "Q", 0, "bing.com", []string{"A"}, 0, []string{}) - utils.AddRetinaMetadata(testQ, metaQ) + extQ := utils.NewExtensions() + utils.AddDNSInfo(testQ, extQ, "Q", 0, "bing.com", []string{"A"}, 0, []string{}) + utils.SetExtensions(testQ, extQ) testU := &flow.Flow{} - metaU := &utils.RetinaMetadata{} - utils.AddDNSInfo(testU, metaU, "U", 0, "bing.com", []string{"A"}, 0, []string{}) - utils.AddRetinaMetadata(testU, metaU) + extU := utils.NewExtensions() + utils.AddDNSInfo(testU, extU, "U", 0, "bing.com", []string{"A"}, 0, []string{}) + utils.SetExtensions(testU, extU) tests := []struct { name string @@ -203,19 +203,19 @@ func TestProcessLocalCtx(t *testing.T) { defer ctrl.Finish() testR := &flow.Flow{} - metaR := &utils.RetinaMetadata{} - utils.AddDNSInfo(testR, metaR, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.AddRetinaMetadata(testR, metaR) + extR := utils.NewExtensions() + utils.AddDNSInfo(testR, extR, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) + utils.SetExtensions(testR, extR) testIngress := &flow.Flow{TrafficDirection: flow.TrafficDirection_INGRESS} - metaIngress := &utils.RetinaMetadata{} - utils.AddDNSInfo(testIngress, metaIngress, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.AddRetinaMetadata(testIngress, metaIngress) + extIngress := utils.NewExtensions() + utils.AddDNSInfo(testIngress, extIngress, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) + utils.SetExtensions(testIngress, extIngress) testEgress := &flow.Flow{TrafficDirection: flow.TrafficDirection_EGRESS} - metaEgress := &utils.RetinaMetadata{} - utils.AddDNSInfo(testEgress, metaEgress, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.AddRetinaMetadata(testEgress, metaEgress) + extEgress := utils.NewExtensions() + utils.AddDNSInfo(testEgress, extEgress, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) + utils.SetExtensions(testEgress, extEgress) tests := []struct { name string diff --git a/pkg/module/metrics/latency_test.go b/pkg/module/metrics/latency_test.go index 79195eecd0..1a78fcb37a 100644 --- a/pkg/module/metrics/latency_test.go +++ b/pkg/module/metrics/latency_test.go @@ -122,20 +122,20 @@ func TestProcessFlow(t *testing.T) { */ // Node -> Api server. f1 := utils.ToFlow(l, t1, apiSeverIp, nodeIp, 80, 443, 6, 3, 0) - metaf1 := &utils.RetinaMetadata{} - utils.AddTCPID(metaf1, 1234) + ext1 := utils.NewExtensions() + utils.AddTCPID(ext1, 1234) utils.AddTCPFlags(f1, 1, 0, 0, 0, 0, 0, 0, 0, 0) - utils.AddRetinaMetadata(f1, metaf1) + utils.SetExtensions(f1, ext1) f1.Destination = &flow.Endpoint{ PodName: "kubernetes-apiserver", } // Api server -> Node. f2 := utils.ToFlow(l, t2, nodeIp, apiSeverIp, 443, 80, 6, 2, 0) - metaf2 := &utils.RetinaMetadata{} - utils.AddTCPID(metaf2, 1234) + ext2 := utils.NewExtensions() + utils.AddTCPID(ext2, 1234) utils.AddTCPFlags(f2, 1, 1, 0, 0, 0, 0, 0, 0, 0) - utils.AddRetinaMetadata(f2, metaf2) + utils.SetExtensions(f2, ext2) f2.Source = &flow.Endpoint{ PodName: "kubernetes-apiserver", } diff --git a/pkg/plugin/dns/dns_linux.go b/pkg/plugin/dns/dns_linux.go index 0e41bb7ca9..9251e03e13 100644 --- a/pkg/plugin/dns/dns_linux.go +++ b/pkg/plugin/dns/dns_linux.go @@ -136,12 +136,12 @@ func (d *dns) eventHandler(event *types.Event) { utils.Verdict_DNS, ) - meta := &utils.RetinaMetadata{} + ext := utils.NewExtensions() - utils.AddDNSInfo(fl, meta, string(event.Qr), common.RCodeToFlow(event.Rcode), event.DNSName, []string{event.QType}, event.NumAnswers, event.Addresses) + utils.AddDNSInfo(fl, ext, string(event.Qr), common.RCodeToFlow(event.Rcode), event.DNSName, []string{event.QType}, event.NumAnswers, event.Addresses) - // Add metadata to the flow. - utils.AddRetinaMetadata(fl, meta) + // Set extensions on the flow. + utils.SetExtensions(fl, ext) ev := (&v1.Event{ Event: fl, diff --git a/pkg/plugin/dropreason/dropreason_linux.go b/pkg/plugin/dropreason/dropreason_linux.go index c22dc11770..d660ddaf6d 100644 --- a/pkg/plugin/dropreason/dropreason_linux.go +++ b/pkg/plugin/dropreason/dropreason_linux.go @@ -318,16 +318,16 @@ func (dr *dropReason) processRecord(ctx context.Context, id int) { // IsReply is not applicable for DROPPED verdicts. fl.IsReply = nil - meta := &utils.RetinaMetadata{} + ext := utils.NewExtensions() - // Add drop reason to the flow's metadata. - utils.AddDropReason(fl, meta, bpfEvent.DropType) + // Add drop reason to the flow's extensions. + utils.AddDropReason(fl, ext, bpfEvent.DropType) - // Add packet size to the flow's metadata. - utils.AddPacketSize(meta, bpfEvent.SkbLen) + // Add packet size to the flow's extensions. + utils.AddPacketSize(ext, bpfEvent.SkbLen) - // Add metadata to the flow. - utils.AddRetinaMetadata(fl, meta) + // Set extensions on the flow. + utils.SetExtensions(fl, ext) // This is only for development purposes. // Removing this makes logs way too chatter-y. diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index f6f5389962..b89773699d 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -608,14 +608,14 @@ func (p *packetParser) processRecord(ctx context.Context, id int) { // Add the traffic direction to the flow. fl.TrafficDirection = flow.TrafficDirection(bpfEvent.TrafficDirection) - meta := &utils.RetinaMetadata{} + ext := utils.NewExtensions() - // Add packet size to the flow's metadata. - utils.AddPacketSize(meta, bpfEvent.Bytes) + // Add packet size to the flow's extensions. + utils.AddPacketSize(ext, bpfEvent.Bytes) - // Add previously observed byte and packet counts to the flow's metadata - utils.AddPreviouslyObservedBytes(meta, bpfEvent.PreviouslyObservedBytes) - utils.AddPreviouslyObservedPackets(meta, bpfEvent.PreviouslyObservedPackets) + // Add previously observed byte and packet counts to the flow's extensions + utils.AddPreviouslyObservedBytes(ext, bpfEvent.PreviouslyObservedBytes) + utils.AddPreviouslyObservedPackets(ext, bpfEvent.PreviouslyObservedPackets) // Add the TCP metadata to the flow. tcpMetadata := bpfEvent.TcpMetadata @@ -632,7 +632,7 @@ func (p *packetParser) processRecord(ctx context.Context, id int) { uint16((bpfEvent.Flags&TCPFlagNS)>>8), // nolint:gomnd // 8 is the offset for NS. ) utils.AddPreviouslyObservedTCPFlags( - meta, + ext, bpfEvent.PreviouslyObservedFlags.Syn, bpfEvent.PreviouslyObservedFlags.Ack, bpfEvent.PreviouslyObservedFlags.Fin, @@ -647,13 +647,13 @@ func (p *packetParser) processRecord(ctx context.Context, id int) { // For packets originating from node, we use tsval as the tcpID. // Packets coming back has the tsval echoed in tsecr. if fl.GetTraceObservationPoint() == flow.TraceObservationPoint_TO_NETWORK { - utils.AddTCPID(meta, uint64(tcpMetadata.Tsval)) + utils.AddTCPID(ext, uint64(tcpMetadata.Tsval)) } else if fl.GetTraceObservationPoint() == flow.TraceObservationPoint_FROM_NETWORK { - utils.AddTCPID(meta, uint64(tcpMetadata.Tsecr)) + utils.AddTCPID(ext, uint64(tcpMetadata.Tsecr)) } - // Add metadata to the flow. - utils.AddRetinaMetadata(fl, meta) + // Set extensions on the flow. + utils.SetExtensions(fl, ext) // Write the event to the enricher. ev := &v1.Event{ diff --git a/pkg/utils/flow_utils.go b/pkg/utils/flow_utils.go index 1ad3b84c3b..0313d36ca2 100644 --- a/pkg/utils/flow_utils.go +++ b/pkg/utils/flow_utils.go @@ -11,6 +11,7 @@ import ( "github.com/microsoft/retina/pkg/log" "go.uber.org/zap" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -22,6 +23,18 @@ const ( TypeUrl string = "retina.sh" ) +// Extension field keys for structpb.Struct +const ( + ExtKeyBytes = "bytes" + ExtKeyDNSType = "dns_type" + ExtKeyNumResponses = "num_responses" + ExtKeyTCPID = "tcp_id" + ExtKeyDropReason = "drop_reason" + ExtKeyPrevObservedPackets = "previously_observed_packets" + ExtKeyPrevObservedBytes = "previously_observed_bytes" + ExtKeyPrevObservedTCPFlags = "previously_observed_tcp_flags" +) + // ToFlow returns a flow.Flow object. // This sets up a L3/L4 flow object. // sourceIP, destIP are IPv4 addresses. @@ -95,8 +108,6 @@ func ToFlow( verdict = flow.Verdict_FORWARDED } - ext, _ := anypb.New(&RetinaMetadata{}) //nolint:typecheck - f := &flow.Flow{ Type: flow.FlowType_L3_L4, EventType: &flow.CiliumEventType{ @@ -114,7 +125,6 @@ func ToFlow( // Packetparser running with conntrack can determine the traffic direction correctly and will override this value. TrafficDirection: direction, Verdict: verdict, - Extensions: ext, // Setting IsReply to false by default. // Packetparser running with conntrack can determine the direction of the flow, and will override this value. IsReply: &wrapperspb.BoolValue{Value: false}, @@ -127,12 +137,34 @@ func ToFlow( return f } -// AddRetinaMetadata adds the RetinaMetadata to the flow's extensions field. -func AddRetinaMetadata(f *flow.Flow, meta *RetinaMetadata) { - ext, _ := anypb.New(meta) +// NewExtensions creates a new structpb.Struct for use as flow extensions. +func NewExtensions() *structpb.Struct { + return &structpb.Struct{Fields: make(map[string]*structpb.Value)} +} + +// SetExtensions wraps the struct in Any and sets it on the flow. +// Only call this after populating all extension fields. +func SetExtensions(f *flow.Flow, s *structpb.Struct) { + if f == nil || s == nil || len(s.GetFields()) == 0 { + return + } + ext, _ := anypb.New(s) f.Extensions = ext } +// getExtensionsStruct extracts the structpb.Struct from flow.Extensions. +// Returns nil if Extensions is nil or not a Struct. +func getExtensionsStruct(f *flow.Flow) *structpb.Struct { + if f == nil || f.GetExtensions() == nil { + return nil + } + s := &structpb.Struct{} + if err := f.GetExtensions().UnmarshalTo(s); err != nil { + return nil + } + return s +} + func AddTCPFlags(f *flow.Flow, syn, ack, fin, rst, psh, urg, ece, cwr, ns uint16) { if f.GetL4().GetTCP() == nil { return @@ -151,68 +183,83 @@ func AddTCPFlags(f *flow.Flow, syn, ack, fin, rst, psh, urg, ece, cwr, ns uint16 } } -// AddPreviouslyObservedTCPFlags adds the previously observed TCP flags to the flows's metadata. -func AddPreviouslyObservedTCPFlags(meta *RetinaMetadata, syn, ack, fin, rst, psh, urg, ece, cwr, ns uint32) { - if meta == nil { +// AddPreviouslyObservedTCPFlags adds the previously observed TCP flags to the flow's extensions. +func AddPreviouslyObservedTCPFlags(s *structpb.Struct, syn, ack, fin, rst, psh, urg, ece, cwr, ns uint32) { + if s == nil { return } - meta.PreviouslyObservedTcpFlags = map[string]uint32{ - SYN: syn, - ACK: ack, - FIN: fin, - RST: rst, - PSH: psh, - URG: urg, - ECE: ece, - CWR: cwr, - NS: ns, + // Only add if at least one flag is non-zero + if syn == 0 && ack == 0 && fin == 0 && rst == 0 && psh == 0 && urg == 0 && ece == 0 && cwr == 0 && ns == 0 { + return } + tcpFlags := &structpb.Struct{Fields: map[string]*structpb.Value{ + SYN: structpb.NewNumberValue(float64(syn)), + ACK: structpb.NewNumberValue(float64(ack)), + FIN: structpb.NewNumberValue(float64(fin)), + RST: structpb.NewNumberValue(float64(rst)), + PSH: structpb.NewNumberValue(float64(psh)), + URG: structpb.NewNumberValue(float64(urg)), + ECE: structpb.NewNumberValue(float64(ece)), + CWR: structpb.NewNumberValue(float64(cwr)), + NS: structpb.NewNumberValue(float64(ns)), + }} + s.Fields[ExtKeyPrevObservedTCPFlags] = structpb.NewStructValue(tcpFlags) } func PreviouslyObservedTCPFlags(f *flow.Flow) map[string]uint32 { - e := f.GetExtensions() - if e == nil { + s := getExtensionsStruct(f) + if s == nil { + return nil + } + v, ok := s.GetFields()[ExtKeyPrevObservedTCPFlags] + if !ok || v.GetStructValue() == nil { return nil } - k := &RetinaMetadata{} - e.UnmarshalTo(k) //nolint:errcheck // ignore errors - return k.GetPreviouslyObservedTcpFlags() + result := make(map[string]uint32) + for k, val := range v.GetStructValue().GetFields() { + result[k] = uint32(val.GetNumberValue()) + } + return result } -// AddPreviouslyObservedBytes adds the previously observed bytes to the flow's metadata. -func AddPreviouslyObservedBytes(meta *RetinaMetadata, bytes uint32) { - if meta == nil { +// AddPreviouslyObservedBytes adds the previously observed bytes to the flow's extensions. +func AddPreviouslyObservedBytes(s *structpb.Struct, bytes uint32) { + if s == nil || bytes == 0 { return } - meta.PreviouslyObservedBytes = bytes + s.Fields[ExtKeyPrevObservedBytes] = structpb.NewNumberValue(float64(bytes)) } func PreviouslyObservedBytes(f *flow.Flow) uint32 { - e := f.GetExtensions() - if e == nil { + s := getExtensionsStruct(f) + if s == nil { + return 0 + } + v, ok := s.GetFields()[ExtKeyPrevObservedBytes] + if !ok { return 0 } - k := &RetinaMetadata{} - e.UnmarshalTo(k) //nolint:errcheck // ignore errors - return k.GetPreviouslyObservedBytes() + return uint32(v.GetNumberValue()) } -// AddPreviouslyObservedPackets adds the previously observed packets to the flow's metadata. -func AddPreviouslyObservedPackets(meta *RetinaMetadata, packets uint32) { - if meta == nil { +// AddPreviouslyObservedPackets adds the previously observed packets to the flow's extensions. +func AddPreviouslyObservedPackets(s *structpb.Struct, packets uint32) { + if s == nil || packets == 0 { return } - meta.PreviouslyObservedPackets = packets + s.Fields[ExtKeyPrevObservedPackets] = structpb.NewNumberValue(float64(packets)) } func PreviouslyObservedPackets(f *flow.Flow) uint32 { - e := f.GetExtensions() - if e == nil { + s := getExtensionsStruct(f) + if s == nil { + return 0 + } + v, ok := s.GetFields()[ExtKeyPrevObservedPackets] + if !ok { return 0 } - k := &RetinaMetadata{} - e.UnmarshalTo(k) //nolint:errcheck // ignore errors - return k.GetPreviouslyObservedPackets() + return uint32(v.GetNumberValue()) } func AddTCPFlagsBool(f *flow.Flow, syn, ack, fin, rst, psh, urg bool) { @@ -230,28 +277,34 @@ func AddTCPFlagsBool(f *flow.Flow, syn, ack, fin, rst, psh, urg bool) { } } -// Add TSval/TSecr to the flow's metadata as TCP ID. +// AddTCPID adds TSval/TSecr to the flow's extensions as TCP ID. // The TSval/TSecr works as ID for the flow. // We will use this ID to calculate latency. -func AddTCPID(meta *RetinaMetadata, id uint64) { - if meta == nil { +func AddTCPID(s *structpb.Struct, id uint64) { + if s == nil || id == 0 { return } - meta.TcpId = id + s.Fields[ExtKeyTCPID] = structpb.NewNumberValue(float64(id)) } func GetTCPID(f *flow.Flow) uint64 { if f.GetL4() == nil || f.GetL4().GetTCP() == nil { return 0 } - k := &RetinaMetadata{} //nolint:typecheck - f.Extensions.UnmarshalTo(k) //nolint:errcheck - return k.TcpId + s := getExtensionsStruct(f) + if s == nil { + return 0 + } + v, ok := s.GetFields()[ExtKeyTCPID] + if !ok { + return 0 + } + return uint64(v.GetNumberValue()) } -// AddDNSInfo adds DNS information to the flow's metadata. -func AddDNSInfo(f *flow.Flow, meta *RetinaMetadata, qType string, rCode uint32, query string, qTypes []string, numAnswers int, ips []string) { - if f == nil || meta == nil { +// AddDNSInfo adds DNS information to the flow and its extensions. +func AddDNSInfo(f *flow.Flow, s *structpb.Struct, qType string, rCode uint32, query string, qTypes []string, numAnswers int, ips []string) { + if f == nil || s == nil { return } // Set type to L7. @@ -273,17 +326,18 @@ func AddDNSInfo(f *flow.Flow, meta *RetinaMetadata, qType string, rCode uint32, } switch qType { case "Q": - meta.DnsType = DNSType_QUERY + s.Fields[ExtKeyDNSType] = structpb.NewStringValue(DNSType_QUERY.String()) f.L7.Type = flow.L7FlowType_REQUEST case "R": - meta.DnsType = DNSType_RESPONSE + s.Fields[ExtKeyDNSType] = structpb.NewStringValue(DNSType_RESPONSE.String()) f.L7.Type = flow.L7FlowType_RESPONSE f.IsReply = &wrapperspb.BoolValue{Value: true} // we can definitely say that this is a reply default: - meta.DnsType = DNSType_UNKNOWN f.L7.Type = flow.L7FlowType_UNKNOWN_L7_TYPE } - meta.NumResponses = uint32(numAnswers) + if numAnswers > 0 { + s.Fields[ExtKeyNumResponses] = structpb.NewNumberValue(float64(numAnswers)) + } } func GetDNS(f *flow.Flow) (*flow.DNS, DNSType, uint32) { @@ -291,13 +345,27 @@ func GetDNS(f *flow.Flow) (*flow.DNS, DNSType, uint32) { return nil, DNSType_UNKNOWN, 0 } dns := f.L7.GetDns() - if f.Extensions == nil { + s := getExtensionsStruct(f) + if s == nil { return dns, DNSType_UNKNOWN, 0 } - k := &RetinaMetadata{} //nolint:typecheck - f.Extensions.UnmarshalTo(k) //nolint:errcheck - return dns, k.DnsType, k.NumResponses + dnsType := DNSType_UNKNOWN + if v, ok := s.GetFields()[ExtKeyDNSType]; ok { + switch v.GetStringValue() { + case DNSType_QUERY.String(): + dnsType = DNSType_QUERY + case DNSType_RESPONSE.String(): + dnsType = DNSType_RESPONSE + } + } + + var numResponses uint32 + if v, ok := s.GetFields()[ExtKeyNumResponses]; ok { + numResponses = uint32(v.GetNumberValue()) + } + + return dns, dnsType, numResponses } // DNS Return code to string. @@ -323,38 +391,42 @@ func DNSRcodeToString(f *flow.Flow) string { } } -// AddPacketSize adds the packet size to the flow's metadata. -func AddPacketSize(meta *RetinaMetadata, packetSize uint32) { - if meta == nil { +// AddPacketSize adds the packet size to the flow's extensions. +func AddPacketSize(s *structpb.Struct, packetSize uint32) { + if s == nil || packetSize == 0 { return } - meta.Bytes = packetSize + s.Fields[ExtKeyBytes] = structpb.NewNumberValue(float64(packetSize)) } func PacketSize(f *flow.Flow) uint32 { - if f.Extensions == nil { + s := getExtensionsStruct(f) + if s == nil { return 0 } - k := &RetinaMetadata{} //nolint:typecheck - f.Extensions.UnmarshalTo(k) //nolint:errcheck - return k.Bytes + v, ok := s.GetFields()[ExtKeyBytes] + if !ok { + return 0 + } + return uint32(v.GetNumberValue()) } -// AddDropReason adds the drop reason to the flow's metadata. -func AddDropReason(f *flow.Flow, meta *RetinaMetadata, dropReason uint16) { - if f == nil || meta == nil { +// AddDropReason adds the drop reason to the flow and its extensions. +func AddDropReason(f *flow.Flow, s *structpb.Struct, dropReason uint16) { + if f == nil || s == nil { return } - meta.DropReason = DropReason(dropReason) + dr := DropReason(dropReason) + s.Fields[ExtKeyDropReason] = structpb.NewStringValue(dr.String()) f.Verdict = flow.Verdict_DROPPED // Set the drop reason. // Retina drop reasons are different from the drop reasons available in flow library. // We map the ones available in flow library to the ones available in Retina. - // Rest are set to UNKNOWN. The details are added in the metadata. - f.DropReasonDesc = GetDropReasonDesc(meta.GetDropReason()) + // Rest are set to UNKNOWN. The details are added in the extensions. + f.DropReasonDesc = GetDropReasonDesc(dr) f.EventType = &flow.CiliumEventType{ Type: int32(api.MessageTypeDrop), @@ -366,9 +438,15 @@ func DropReasonDescription(f *flow.Flow) string { if f == nil { return "" } - k := &RetinaMetadata{} //nolint:typecheck // Not required to check type as we are setting it. - f.GetExtensions().UnmarshalTo(k) //nolint:errcheck // Not required to check error as we are setting it. - return k.GetDropReason().String() + s := getExtensionsStruct(f) + if s == nil { + return "" + } + v, ok := s.GetFields()[ExtKeyDropReason] + if !ok { + return "" + } + return v.GetStringValue() } func decodeTime(nanoseconds int64) (pbTime *timestamppb.Timestamp, err error) { diff --git a/pkg/utils/utils_linux_test.go b/pkg/utils/utils_linux_test.go index b672033496..9d5767ac1f 100644 --- a/pkg/utils/utils_linux_test.go +++ b/pkg/utils/utils_linux_test.go @@ -47,7 +47,8 @@ func TestToFlow(t *testing.T) { assert.EqualValues(t, f.GetL4().Protocol.(*flow.Layer4_TCP).TCP.SourcePort, uint32(443)) assert.EqualValues(t, f.GetL4().Protocol.(*flow.Layer4_TCP).TCP.DestinationPort, uint32(80)) assert.NotNil(t, f.Time) - assert.NotNil(t, f.Extensions) + // Extensions are now set separately via SetExtensions() after populating extension fields + assert.Nil(t, f.Extensions) assert.Equal(t, f.Type, flow.FlowType_L3_L4) if !f.GetTime().IsValid() { @@ -87,9 +88,9 @@ func TestAddPacketSize(t *testing.T) { uint8(1), flow.Verdict_FORWARDED, ) - meta := &RetinaMetadata{} - AddPacketSize(meta, uint32(100)) - AddRetinaMetadata(fl, meta) + ext := NewExtensions() + AddPacketSize(ext, uint32(100)) + SetExtensions(fl, ext) res := PacketSize(fl) assert.EqualValues(t, res, uint32(100)) @@ -111,9 +112,9 @@ func TestTcpID(t *testing.T) { flow.Verdict_FORWARDED, ) - meta := &RetinaMetadata{} - AddTCPID(meta, uint64(1234)) - AddRetinaMetadata(fl, meta) + ext := NewExtensions() + AddTCPID(ext, uint64(1234)) + SetExtensions(fl, ext) assert.EqualValues(t, GetTCPID(fl), uint64(1234)) } @@ -154,9 +155,9 @@ func TestAddDropReason(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { f := &flow.Flow{} - meta := &RetinaMetadata{} - AddDropReason(f, meta, tc.dropReason) - AddRetinaMetadata(f, meta) + ext := NewExtensions() + AddDropReason(f, ext, tc.dropReason) + SetExtensions(f, ext) assert.Equal(t, f.DropReasonDesc, tc.expectedDesc) assert.Equal(t, f.Verdict, flow.Verdict_DROPPED) assert.NotNil(t, f.EventType.Type, 1) From 714e9234a5a76e82e74a2d906046112ca8550a10 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 12 Feb 2026 16:32:18 -0500 Subject: [PATCH 209/448] fix(ci): use native arm64 runners for all image builds (#2047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Switch remaining ARM64 image build jobs to native `ubuntu-24.04-arm` runners instead of QEMU emulation on x86 `ubuntu-latest`. This follows the same pattern established for `retina-shell-images` in PR #2024. ## Related Issue Follows up on #2024 (fix(ci): use native arm64 runners for shell image build). ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed YAML syntax validated. Changes are consistent with the existing `retina-shell-images` pattern already running in CI. **Jobs migrated (6 total across 2 files):** | Job | File | |-----|------| | `retina-images` | `images.yaml` | | `operator-images` | `images.yaml` | | `kubectl-retina-images` | `images.yaml` | | `retina-images` | `release-images.yaml` | | `operator-images` | `release-images.yaml` | | `kubectl-retina-images` | `release-images.yaml` | **Changes per job:** - `runs-on`: `ubuntu-latest` → `${{ matrix.runner }}` - Matrix converted from simple arrays to explicit `include` entries with `runner` field (`ubuntu-latest` for amd64, `ubuntu-24.04-arm` for arm64) - Removed `docker/setup-qemu-action` step (no longer needed for native builds) - Updated job names to include `(${{ matrix.platform }}, ${{ matrix.arch }})` for clarity **Not changed:** - `manifests` jobs — still use QEMU as needed for multi-arch manifest inspection - `retina-shell-images` — already migrated in #2024 ## Additional Notes The only remaining `setup-qemu-action` references are in the `manifests` jobs, which correctly still need it. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- .github/workflows/images.yaml | 30 ++++++++++++++++----------- .github/workflows/release-images.yaml | 30 ++++++++++++++++----------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index a509b743e0..bbba14e0f0 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -14,12 +14,17 @@ permissions: jobs: retina-images: name: Build Agent Images - Linux - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: matrix: platform: ["linux"] arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -30,9 +35,6 @@ jobs: go-version-file: go.mod - run: go version - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Az CLI login uses: azure/login@v2 if: ${{ github.event_name == 'merge_group' }} @@ -154,12 +156,17 @@ jobs: operator-images: name: Build Operator Images - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: matrix: platform: ["linux"] arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -170,9 +177,6 @@ jobs: go-version-file: go.mod - run: go version - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Az CLI login uses: azure/login@v2 if: ${{ github.event_name == 'merge_group' }} @@ -255,12 +259,17 @@ jobs: kubectl-retina-images: name: Build Kubectl Retina Images - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: matrix: platform: ["linux"] arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -271,9 +280,6 @@ jobs: go-version-file: go.mod - run: go version - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Az CLI login uses: azure/login@v2 if: ${{ github.event_name == 'merge_group' }} diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 31c9ccba8b..27a0c1eeaa 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -15,12 +15,17 @@ permissions: jobs: retina-images: name: Build Agent Images - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: matrix: platform: ["linux"] arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -34,9 +39,6 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v4.0.0 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -140,12 +142,17 @@ jobs: operator-images: name: Build Operator Images - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: matrix: platform: ["linux"] arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -159,9 +166,6 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v4.0.0 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -230,12 +234,17 @@ jobs: kubectl-retina-images: name: Build Kubectl Retina Images - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: matrix: platform: ["linux"] arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -249,9 +258,6 @@ jobs: - name: Install Cosign uses: sigstore/cosign-installer@v4.0.0 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From 60edb4d970417313d1a8d8c3e4491f60ffe22d15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 20:26:11 -0500 Subject: [PATCH 210/448] deps: bump github.com/aws/aws-sdk-go-v2/credentials from 1.18.10 to 1.19.7 (#2014) Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.18.10 to 1.19.7.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/credentials&package-manager=go_modules&previous-version=1.18.10&new-version=1.19.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index d49a339a6f..330be0742f 100644 --- a/go.mod +++ b/go.mod @@ -47,18 +47,18 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect github.com/aws/smithy-go v1.24.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 @@ -272,9 +272,9 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.40.1 + github.com/aws/aws-sdk-go-v2 v1.41.1 github.com/aws/aws-sdk-go-v2/config v1.31.6 - github.com/aws/aws-sdk-go-v2/credentials v1.18.10 + github.com/aws/aws-sdk-go-v2/credentials v1.19.7 github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 diff --git a/go.sum b/go.sum index db2ec919d6..06e1b9f0bb 100644 --- a/go.sum +++ b/go.sum @@ -244,22 +244,22 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.40.1 h1:difXb4maDZkRH0x//Qkwcfpdg1XQVXEAEs2DdXldFFc= -github.com/aws/aws-sdk-go-v2 v1.40.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= +github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ= -github.com/aws/aws-sdk-go-v2/credentials v1.18.10 h1:xdJnXCouCx8Y0NncgoptztUocIYLKeQxrCgN6x9sdhg= -github.com/aws/aws-sdk-go-v2/credentials v1.18.10/go.mod h1:7tQk08ntj914F/5i9jC4+2HQTAuJirq7m1vZVIhEkWs= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 h1:wbjnrrMnKew78/juW7I2BtKQwa1qlf6EjQgS69uYY14= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6/go.mod h1:AtiqqNrDioJXuUgz3+3T0mBWN7Hro2n9wll2zRUc0ww= +github.com/aws/aws-sdk-go-v2/credentials v1.19.7 h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.7/go.mod h1:qOZk8sPDrxhf+4Wf4oT2urYJrYt3RejHSzgAquYeppw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 h1:Y5YXgygXwDI5P4RkteB5yF7v35neH7LfJKBG+hzIons= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15/go.mod h1:K+/1EpG42dFSY7CBj+Fruzm8PsCGWTXJ3jdeJ659oGQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 h1:AvltKnW9ewxX2hFmQS0FyJH93aSvJVUEFvXfU+HWtSE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15/go.mod h1:3I4oCdZdmgrREhU74qS1dK9yZ62yumob+58AbFR4cQA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 h1:NLYTEyZmVZo0Qh183sC8nC+ydJXOOeIL/qI/sS3PdLY= @@ -272,20 +272,20 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEd github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 h1:P1MU/SuhadGvg2jtviDXPEejU3jBNhoeeAlRadHzvHI= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6/go.mod h1:5KYaMG6wmVKMFBSfWoyG/zH8pWwzQFnKgpoSRlXHKdQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 h1:3/u/4yZOffg5jdNk1sDpOQ4Y+R6Xbh+GzpDrSZjuy3U= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15/go.mod h1:4Zkjq0FKjE78NKjabuM4tRXKFzUJWXgP0ItEZK8l7JU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 h1:wsSQ4SVz5YE1crz0Ap7VBZrV4nNqZt4CIBBT8mnwoNc= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15/go.mod h1:I7sditnFGtYMIqPRU1QoHZAUrXkGp4SczmlLwrNPlD0= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 h1:IrbE3B8O9pm3lsg96AXIN5MXX4pECEuExh/A0Du3AuI= github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0/go.mod h1:/sJLzHtiiZvs6C1RbxS/anSAFwZD6oC6M/kotQzOiLw= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 h1:8OLZnVJPvjnrxEwHFg9hVUof/P4sibH+Ea4KKuqAGSg= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.1/go.mod h1:27M3BpVi0C02UiQh1w9nsBEit6pLhlaH3NHna6WUbDE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 h1:gKWSTnqudpo8dAxqBqZnDoDWCiEh/40FziUjr/mo6uA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2/go.mod h1:x7+rkNmRoEN1U13A6JE2fXne9EWyJy54o3n6d4mGaXQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 h1:YZPjhyaGzhDQEvsffDEcpycq49nl7fiGcfJTIo8BszI= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.2/go.mod h1:2dIN8qhQfv37BdUYGgEC8Q3tteM3zFxTI1MLO2O3J3c= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 h1:gd84Omyu9JLriJVCbGApcLzVR3XtmC4ZDPcAI6Ftvds= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= From 180822f6d5f7c4945bfe380ec2e1afc5feb3e921 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 13 Feb 2026 13:32:38 -0500 Subject: [PATCH 211/448] chore(ci): harden CI pipelines and fix devcontainer (#2060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Comprehensive CI hardening across all workflow files, devcontainer fixes, and coverage reporting. ### Actions pinned to SHA - Pin all 50+ GitHub Action references to SHA digests with version comments - Bump to latest versions: CodeQL v4.32.3, golangci-lint-action v9.2.0, goreleaser-action v6.4.0, markdownlint-cli2-action v22.0.0, trivy-action 0.34.0, create-pull-request v8.1.0, stale v10.1.1, and others - Eliminates supply chain risk from mutable version tags (including `actions/stale@main`) ### Workflow hardening - **Concurrency groups** added to 8 workflows to cancel duplicate runs - **timeout-minutes** added to all 37 jobs across all workflows - **Explicit permissions** added to workflows missing them (commit-message, test-multicloud, markdownlint, release-validation) - **Permissions reduced** in test.yaml (removed unnecessary issues/pull-requests/security-events write) - **Path filters** added to docs and markdownlint workflows ### Bug fixes - **Trivy**: skip scan when triggering release workflow failed (eliminates ~82% of trivy failures); use latest release tag for scheduled/manual scans instead of HEAD SHA - **Merge queue bypass removed**: golangci-lint and CodeQL now run on merge_group events - **Shell expansion fix**: `$(make version)` and `$(curl ...)` in YAML `with:` blocks don't execute — restructured perf-schedule.yaml with a `get-tag` job and fixed images.yaml perf-test calls - **Release validation**: only runs when triggering workflow succeeded - **Stale outputs**: quoted to prevent injection - **Coverage scripts**: fixed hardcoded `owner = "azure"` → `"microsoft"`, fixed workflow filename `"retina-test.yaml"` → `"test.yaml"`, added guard for empty workflow runs - **Makefile coverage target**: fixed grep pattern that silently failed to filter `_generated.go` files (mixed escaped/unescaped `|` in BRE mode) ### Test coverage reporting - **Step summary**: every test run now posts total coverage percentage and lowest-coverage packages to `$GITHUB_STEP_SUMMARY` - **PR comment**: on pull requests, fetches main branch coverage, diffs it, and posts/updates a coverage comparison comment showing per-file increases/decreases - Handles 403 gracefully for fork PRs (insufficient `GITHUB_TOKEN` permissions) — falls back to step summary - Wires up the existing but disconnected `scripts/coverage/` infrastructure ### GoReleaser - Added `checksum` and `sboms` sections for release artifact integrity ### Devcontainer - Upgraded base image from Ubuntu Jammy (22.04) to Noble (24.04) - Pinned Go version to 1.24.11 (matches go.mod) - Fixed LLVM/Clang from version 14 to 16 (matches project requirements) - Added `clang` and `llvm-strip` symlinks - Installed `gofumpt` (required by `make fmt`) - Added docker readiness check before `kind create cluster` - Hardened install script with `set -euo pipefail` - Removed redundant `common-utils` feature ## Related Issue N/A — proactive hardening based on CI failure analysis. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed - Verified zero unpinned actions remain (`grep` for `@v\d` and `@main` returns no matches) - Verified zero `IS_NOT_MERGE_GROUP` references remain - Verified all 37 jobs have `timeout-minutes` set - YAML syntax validated across all workflow files Signed-off-by: Quang Nguyen --- .devcontainer/devcontainer.json | 11 +-- .devcontainer/installMoreTools.sh | 25 +++++- .github/workflows/codeql.yaml | 20 ++--- .github/workflows/commit-message.yaml | 5 ++ .github/workflows/docs.yaml | 18 +++-- .github/workflows/e2e-test-event-writer.yml | 3 +- .github/workflows/e2e.yaml | 3 +- .github/workflows/golangci-lint.yaml | 15 ++-- .github/workflows/goreleaser.yaml | 14 +++- .github/workflows/images.yaml | 57 +++++++++---- .github/workflows/markdownlint.yaml | 9 ++- .github/workflows/perf-schedule.yaml | 21 ++++- .github/workflows/perf-template.yaml | 3 +- .github/workflows/release-charts.yaml | 9 ++- .github/workflows/release-images.yaml | 27 ++++--- .github/workflows/release-validation.yaml | 9 ++- .github/workflows/scale-test.yaml | 3 +- .github/workflows/stale.yaml | 5 +- .github/workflows/test-multicloud.yml | 12 ++- .github/workflows/test.yaml | 90 +++++++++++++++++++-- .github/workflows/trivy.yaml | 15 +++- .github/workflows/update-hubble.yaml | 3 +- .goreleaser.yaml | 6 ++ Makefile | 2 +- scripts/coverage/compare_cov.py | 30 ++++--- scripts/coverage/get_coverage.py | 11 ++- 26 files changed, 327 insertions(+), 99 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index dadb65d427..25b94482ce 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,16 +1,17 @@ { "name": "retina", - "image": "mcr.microsoft.com/devcontainers/base:jammy", + "image": "mcr.microsoft.com/devcontainers/base:noble", "features": { - "ghcr.io/devcontainers/features/common-utils:2": {}, "ghcr.io/devcontainers/features/docker-in-docker:2": {}, "ghcr.io/devcontainers/features/github-cli:1": {}, - "ghcr.io/devcontainers/features/go:1": {}, + "ghcr.io/devcontainers/features/go:1": { + "version": "1.24.11" + }, "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}, - "ghcr.io/devcontainers-contrib/features/kind:1": {}, + "ghcr.io/devcontainers-extra/features/kind:1": {}, "ghcr.io/devcontainers/features/azure-cli:1": {} }, - "postCreateCommand": "bash .devcontainer/installMoreTools.sh && kind create cluster", + "postCreateCommand": "bash .devcontainer/installMoreTools.sh && while ! docker info >/dev/null 2>&1; do sleep 1; done && kind create cluster", "customizations": { "vscode": { "extensions": [ diff --git a/.devcontainer/installMoreTools.sh b/.devcontainer/installMoreTools.sh index 8d8fc3b369..185ef14b93 100755 --- a/.devcontainer/installMoreTools.sh +++ b/.devcontainer/installMoreTools.sh @@ -1,8 +1,25 @@ #!/bin/bash +set -euo pipefail + +LLVM_VERSION=16 # Install the required tools and dependencies -sudo apt-get update && sudo apt-get install -y lsb-release wget software-properties-common gnupg clang-14 lldb-14 lld-14 clangd-14 man-db +sudo apt-get update && sudo apt-get install -y \ + lsb-release \ + wget \ + software-properties-common \ + gnupg \ + man-db + +# Install LLVM/Clang (version must match project requirements) +curl -fsSL https://apt.llvm.org/llvm.sh -o /tmp/llvm.sh +chmod +x /tmp/llvm.sh +sudo /tmp/llvm.sh "$LLVM_VERSION" +rm /tmp/llvm.sh + +# Create unversioned symlinks so the build system finds clang and llvm-strip +sudo ln -sf "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang +sudo ln -sf "/usr/bin/llvm-strip-${LLVM_VERSION}" /usr/bin/llvm-strip -# Install LLVM 14 -export LLVM_VERSION=14 -curl -sL https://apt.llvm.org/llvm.sh | sudo bash -s "$LLVM_VERSION" +# Install gofumpt (used by make fmt) +go install mvdan.cc/gofumpt@latest diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 274fc197ec..657e5d7b5f 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -6,6 +6,14 @@ on: branches: [main] pull_request: branches: [main] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: analyze: name: Analyze @@ -17,7 +25,6 @@ jobs: language: [go] runs-on: ubuntu-latest env: - IS_NOT_MERGE_GROUP: ${{ github.event_name != 'merge_group' }} GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} timeout-minutes: 90 @@ -27,23 +34,18 @@ jobs: security-events: write steps: - name: Checkout repository - if: env.IS_NOT_MERGE_GROUP uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - if: env.IS_NOT_MERGE_GROUP uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod - name: Initialize CodeQL - if: env.IS_NOT_MERGE_GROUP - uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: languages: ${{ matrix.language }} - name: Autobuild - if: env.IS_NOT_MERGE_GROUP - uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 - name: Perform CodeQL Analysis - if: env.IS_NOT_MERGE_GROUP - uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/commit-message.yaml b/.github/workflows/commit-message.yaml index ea7e1a1128..3c9d30a17d 100644 --- a/.github/workflows/commit-message.yaml +++ b/.github/workflows/commit-message.yaml @@ -8,10 +8,15 @@ on: - synchronize - edited - reopened + +permissions: + contents: read + jobs: commit-message: if: ${{ github.event_name != 'merge_group' }} runs-on: ubuntu-24.04 + timeout-minutes: 5 steps: - name: verify_commit_message env: diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index ec20c37db8..c81a8b6cfb 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -3,8 +3,14 @@ name: Build and Deploy Retina.sh on: push: branches: ["main"] + paths: + - 'site/**' + - 'docs/**' pull_request: branches: ["main"] + paths: + - 'site/**' + - 'docs/**' workflow_dispatch: merge_group: permissions: @@ -17,10 +23,11 @@ concurrency: jobs: build: runs-on: ubuntu-latest + timeout-minutes: 15 steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-node@v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: node-version: 20 - name: build @@ -29,7 +36,7 @@ jobs: npm run build --prefix site/ - name: Upload build artifact if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@v4 + uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 with: path: "./site/build" @@ -37,12 +44,13 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: build environment: - name: retina.sh + name: retina.sh url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Setup Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/e2e-test-event-writer.yml b/.github/workflows/e2e-test-event-writer.yml index 3ec5625c8e..f8b00b8e6f 100644 --- a/.github/workflows/e2e-test-event-writer.yml +++ b/.github/workflows/e2e-test-event-writer.yml @@ -20,6 +20,7 @@ jobs: retina-win-e2e-bpf-images: name: Build E2E Test Event Writer runs-on: windows-2022 + timeout-minutes: 30 env: IS_MERGE_GROUP: ${{ (github.event_name == 'merge_group') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/dev/v0.0.33-windows' && github.repository == 'microsoft/retina') }} @@ -31,4 +32,4 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 806925738d..fb0be2dafc 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -83,6 +83,7 @@ jobs: e2e: name: E2E runs-on: ubuntu-latest + timeout-minutes: 120 steps: - name: Checkout code @@ -95,7 +96,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 4d5df60fff..d9ed7ab093 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -6,6 +6,14 @@ on: branches: [main] pull_request: branches: [main] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: golangci: strategy: @@ -15,22 +23,19 @@ jobs: goarch: ["amd64", "arm64"] name: Lint runs-on: ubuntu-latest + timeout-minutes: 30 env: - IS_NOT_MERGE_GROUP: ${{ github.event_name != 'merge_group' }} GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - if: env.IS_NOT_MERGE_GROUP with: fetch-depth: 0 - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 - if: env.IS_NOT_MERGE_GROUP with: go-version-file: go.mod - name: golangci-lint - if: env.IS_NOT_MERGE_GROUP - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 with: version: latest args: --concurrency 4 --verbose --config=.golangci.yaml --timeout=25m diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index c932728484..7caaa12e81 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -4,14 +4,21 @@ on: branches: [main] push: tags: ["v*"] + permissions: contents: write packages: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: Build kubectl-retina if: github.ref_type == 'branch' runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -22,7 +29,7 @@ jobs: with: go-version-file: go.mod - name: Run GoReleaser build - uses: goreleaser/goreleaser-action@v6 + uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 env: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent with: @@ -32,6 +39,7 @@ jobs: release: name: Release kubectl-retina runs-on: ubuntu-latest + timeout-minutes: 30 if: github.ref_type == 'tag' steps: - name: Checkout @@ -43,7 +51,7 @@ jobs: with: go-version-file: go.mod - name: Run GoReleaser release - uses: goreleaser/goreleaser-action@v6 + uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 with: distribution: goreleaser version: latest @@ -53,4 +61,4 @@ jobs: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent - name: Update new version in krew-index if: github.repository_owner == 'microsoft' - uses: rajatjindal/krew-release-bot@v0.0.47 + uses: rajatjindal/krew-release-bot@3d9faef30a82761d610544f62afddca00993eef9 # v0.0.47 diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index bbba14e0f0..5a5cae012c 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -11,10 +11,28 @@ permissions: contents: read id-token: write +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: + get-tag: + name: Get Image Tag + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + tag: ${{ steps.get_tag.outputs.tag }} + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Get tag + id: get_tag + run: echo "tag=$(make version)" >> $GITHUB_OUTPUT + retina-images: name: Build Agent Images - Linux runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -36,7 +54,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -67,7 +85,8 @@ jobs: build-windows-binaries: name: Build Windows Binaries runs-on: ubuntu-latest - + timeout-minutes: 30 + steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -91,7 +110,7 @@ jobs: APP_INSIGHTS_ID: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} - name: Upload Windows Binaries - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: windows-binaries path: output/windows_amd64/ @@ -101,6 +120,7 @@ jobs: name: Build Agent Image - Windows ${{ matrix.year }} needs: build-windows-binaries runs-on: windows-${{ matrix.year }} + timeout-minutes: 60 strategy: matrix: @@ -113,13 +133,13 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries - uses: actions/download-artifact@v7 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: windows-binaries path: output/windows_amd64/ - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -157,6 +177,7 @@ jobs: operator-images: name: Build Operator Images runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -178,7 +199,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -209,6 +230,7 @@ jobs: retina-shell-images: name: Build Retina Shell Images (${{ matrix.platform }}, ${{ matrix.arch }}) runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -230,7 +252,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -260,6 +282,7 @@ jobs: kubectl-retina-images: name: Build Kubectl Retina Images runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -281,7 +304,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -312,6 +335,7 @@ jobs: name: Generate Manifests if: ${{ github.event_name == 'merge_group' }} runs-on: ubuntu-latest + timeout-minutes: 30 needs: [ retina-images, @@ -330,10 +354,10 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Azure CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -352,6 +376,7 @@ jobs: if: ${{ github.event_name == 'merge_group' }} needs: [manifests] runs-on: ubuntu-latest + timeout-minutes: 90 steps: - name: Checkout code @@ -364,7 +389,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -382,11 +407,11 @@ jobs: perf-test-basic: if: ${{ github.event_name == 'merge_group'}} - needs: [manifests] + needs: [manifests, get-tag] uses: ./.github/workflows/perf-template.yaml with: image-registry: ${{ vars.ACR_NAME }} - tag: $(make version) + tag: ${{ needs.get-tag.outputs.tag }} image-namespace: ${{ github.repository }} retina-mode: basic azure-location: ${{ vars.AZURE_LOCATION }} @@ -395,14 +420,14 @@ jobs: azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} azure-app-insights-key: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} - + perf-test-advanced: if: ${{ github.event_name == 'merge_group'}} - needs: [manifests] + needs: [manifests, get-tag] uses: ./.github/workflows/perf-template.yaml with: image-registry: ${{ vars.ACR_NAME }} - tag: $(make version) + tag: ${{ needs.get-tag.outputs.tag }} image-namespace: ${{ github.repository }} retina-mode: advanced azure-location: ${{ vars.AZURE_LOCATION }} diff --git a/.github/workflows/markdownlint.yaml b/.github/workflows/markdownlint.yaml index 67a957da3d..cb383f3dd2 100644 --- a/.github/workflows/markdownlint.yaml +++ b/.github/workflows/markdownlint.yaml @@ -3,15 +3,22 @@ on: merge_group: pull_request: branches: [main] + paths: + - '**/*.md' + +permissions: + contents: read + jobs: markdownlint: if: ${{ github.event_name != 'merge_group' }} name: markdownlint runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: DavidAnson/markdownlint-cli2-action@v9 + - uses: DavidAnson/markdownlint-cli2-action@07035fd053f7be764496c0f8d8f9f41f98305101 # v22.0.0 with: command: config globs: | diff --git a/.github/workflows/perf-schedule.yaml b/.github/workflows/perf-schedule.yaml index ee0886626c..92eed22c78 100644 --- a/.github/workflows/perf-schedule.yaml +++ b/.github/workflows/perf-schedule.yaml @@ -10,11 +10,27 @@ permissions: id-token: write jobs: + get-tag: + name: Get Latest Release Tag + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + tag: ${{ steps.get_tag.outputs.tag }} + steps: + - name: Get latest release tag + id: get_tag + env: + GH_TOKEN: ${{ github.token }} + run: | + TAG=$(gh release view --repo ${{ github.repository }} --json tagName -q .tagName) + echo "tag=$TAG" >> $GITHUB_OUTPUT + perf-test-basic: + needs: get-tag uses: ./.github/workflows/perf-template.yaml with: image-registry: ghcr.io - tag: $(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name) + tag: ${{ needs.get-tag.outputs.tag }} image-namespace: ${{ github.repository }} retina-mode: basic azure-location: ${{ vars.AZURE_LOCATION }} @@ -25,10 +41,11 @@ jobs: azure-app-insights-key: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} perf-test-advanced: + needs: get-tag uses: ./.github/workflows/perf-template.yaml with: image-registry: ghcr.io - tag: $(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name) + tag: ${{ needs.get-tag.outputs.tag }} image-namespace: ${{ github.repository }} retina-mode: advanced azure-location: ${{ vars.AZURE_LOCATION }} diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index be43fd7d29..e383d86a41 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -46,6 +46,7 @@ jobs: perf-test: name: Retina ${{ inputs.retina-mode }} Performance Test runs-on: ubuntu-latest + timeout-minutes: 150 steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -57,7 +58,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 with: client-id: ${{ secrets.azure-client-id }} tenant-id: ${{ secrets.azure-tenant-id }} diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index e1daaf6631..218474b288 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -16,6 +16,7 @@ jobs: push-retina-charts: name: Publish Retina Helm Charts runs-on: ubuntu-latest + timeout-minutes: 30 if: github.ref_type == 'tag' steps: - name: Checkout code @@ -23,17 +24,17 @@ jobs: with: fetch-depth: 0 - - uses: azure/setup-helm@v4.3.1 + - uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1 id: install - + - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u $ --password-stdin echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - + - name: Build, Push and Sign chart id: build_chart shell: bash diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 27a0c1eeaa..d3f7f436fc 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -16,6 +16,7 @@ jobs: retina-images: name: Build Agent Images runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -37,7 +38,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -63,7 +64,8 @@ jobs: build-windows-binaries: name: Build Windows Binaries runs-on: ubuntu-latest - + timeout-minutes: 30 + steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -84,7 +86,7 @@ jobs: TAG=$TAG - name: Upload Windows Binaries - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: windows-binaries path: output/windows_amd64/ @@ -94,6 +96,7 @@ jobs: name: Build Agent Image - Windows ${{ matrix.year }} needs: build-windows-binaries runs-on: windows-${{ matrix.year }} + timeout-minutes: 60 strategy: matrix: @@ -106,13 +109,13 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries - uses: actions/download-artifact@v7 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: windows-binaries path: output/windows_amd64/ - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -143,6 +146,7 @@ jobs: operator-images: name: Build Operator Images runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -164,7 +168,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -190,6 +194,7 @@ jobs: retina-shell-images: name: Build Retina Shell Images (${{ matrix.platform }}, ${{ matrix.arch }}) runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -211,7 +216,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -235,6 +240,7 @@ jobs: kubectl-retina-images: name: Build Kubectl Retina Images runs-on: ${{ matrix.runner }} + timeout-minutes: 60 strategy: matrix: @@ -256,7 +262,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -280,6 +286,7 @@ jobs: manifests: name: Generate Manifests runs-on: ubuntu-latest + timeout-minutes: 30 needs: [ retina-images, @@ -298,10 +305,10 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Install Cosign - uses: sigstore/cosign-installer@v4.0.0 + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index f4370b4fdc..6f53292b3e 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -6,13 +6,18 @@ on: types: - completed +permissions: + contents: read + jobs: release_validation: + if: ${{ github.event.workflow_run.conclusion == 'success' }} name: Release Validation runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout repository - uses: actions/checkout@v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest tag id: get_latest_tag @@ -40,7 +45,7 @@ jobs: helm pull oci://ghcr.io/microsoft/retina/charts/retina --version ${{ env.TAG }} - name: Setup kind cluster - uses: helm/kind-action@v1.13.0 + uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0 # krew does not support installing a specific verison # so if this step fails it means there was something wrong diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 954f1f67bf..e50409ae9c 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -65,6 +65,7 @@ jobs: scale-test: name: Scale Test runs-on: ubuntu-latest + timeout-minutes: 360 steps: - name: Checkout code @@ -77,7 +78,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 12eebe7143..cb6f074313 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -7,12 +7,13 @@ on: jobs: stale: runs-on: ubuntu-latest + timeout-minutes: 15 permissions: contents: write issues: write pull-requests: write steps: - - uses: actions/stale@main + - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 id: stale with: ascending: true @@ -31,4 +32,4 @@ jobs: stale-issue-message: "This issue will be closed in 7 days due to inactivity." stale-pr-message: "This PR will be closed in 7 days due to inactivity." - name: Print outputs - run: echo ${{ join(steps.stale.outputs.*, ',') }} + run: echo "${{ join(steps.stale.outputs.*, ',') }}" diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index fba77a7590..ca1f15368a 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -5,12 +5,20 @@ on: paths: - 'test/multicloud/**' +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: multicloud-test: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - - uses: opentofu/setup-opentofu@v1 + - uses: opentofu/setup-opentofu@9d84900f3238fab8cd84ce47d658d25dd008be2f # v1.0.8 with: tofu_version: 1.8.3 @@ -28,4 +36,4 @@ jobs: - name: Run tests run: make test - working-directory: test/multicloud/ \ No newline at end of file + working-directory: test/multicloud/ diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 05a22804b6..71a6a10f4f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -9,17 +9,18 @@ on: workflow_dispatch: permissions: - actions: read contents: read - deployments: read - packages: none pull-requests: write - security-events: write - issues: write + actions: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: test-image: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -40,3 +41,82 @@ jobs: with: name: coverage-files path: ./artifacts/coverage* + + - name: Generate coverage summary + run: | + COVERAGE_FILE="./artifacts/coverage.out" + if [ ! -s "$COVERAGE_FILE" ]; then + echo "::warning::Coverage file is empty or missing" + echo "## Test Coverage" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo ":warning: No coverage data available." >> "$GITHUB_STEP_SUMMARY" + exit 0 + fi + + # Filter out generated files (eBPF, mocks) + grep -Ev '_bpf\.go|_bpfel_x86\.go|_bpfel_arm64\.go|_generated\.go|mock_' "$COVERAGE_FILE" > coverage_filtered.out + + # Generate function-level coverage report + go tool cover -func=coverage_filtered.out > coverage_func.out + + # Extract total coverage percentage + TOTAL_COVERAGE=$(grep '^total:' coverage_func.out | awk '{print $NF}') + + # Write step summary + { + echo "## Test Coverage" + echo "" + echo ":white_check_mark: **Tests passed**" + echo "" + echo "| Metric | Value |" + echo "| --- | --- |" + echo "| Total Coverage | \`${TOTAL_COVERAGE}\` |" + echo "" + echo "
" + echo "Coverage by package (top 20 lowest)" + echo "" + echo '```' + grep -v '^total:' coverage_func.out | sort -t'%' -k1 -n | head -20 + echo '```' + echo "
" + } >> "$GITHUB_STEP_SUMMARY" + + - name: Compare coverage with main branch + if: github.event_name == 'pull_request' + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + run: | + COVERAGE_FILE="./artifacts/coverage.out" + if [ ! -s "$COVERAGE_FILE" ]; then + echo "Coverage file is empty or missing, skipping comparison" + exit 0 + fi + + # Filter generated files and prepare current branch coverage + grep -Ev '_bpf\.go|_bpfel_x86\.go|_bpfel_arm64\.go|_generated\.go|mock_' "$COVERAGE_FILE" > coveragenew.out + cp coveragenew.out coverage.out + go tool cover -func=coveragenew.out -o coverageexpanded.out + + # Install Python dependency for GitHub API calls + pip install --quiet requests + + # Fetch main branch coverage + python3 scripts/coverage/get_coverage.py + + # Check if main branch coverage was downloaded + if [ ! -f mainbranchcoverage/coverage.out ]; then + echo "No main branch coverage found, skipping comparison" + exit 0 + fi + + # Filter main branch coverage + grep -Ev '_bpf\.go|_bpfel_x86\.go|_bpfel_arm64\.go|_generated\.go|mock_' mainbranchcoverage/coverage.out > mainbranchcoverage/coverage_filtered.out + mv mainbranchcoverage/coverage_filtered.out mainbranchcoverage/coverage.out + + # Generate expanded coverage for main branch + go tool cover -func=mainbranchcoverage/coverage.out -o maincoverageexpanded.out + + # Post PR comment with coverage diff + python3 scripts/coverage/compare_cov.py diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 6e4b082235..c0b3af3eb5 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -12,6 +12,7 @@ permissions: contents: read jobs: scan: + if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} permissions: contents: read security-events: write @@ -21,16 +22,24 @@ jobs: matrix: image: ["retina-agent", "retina-init", "retina-operator", "kubectl-retina", "retina-shell"] runs-on: ubuntu-latest # trivy only supports running on Linux + timeout-minutes: 30 steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get Tag + env: + GH_TOKEN: ${{ github.token }} run: | - echo "TAG=$(make version)" >> $GITHUB_ENV + if [ "${{ github.event_name }}" = "schedule" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + TAG=$(gh release view --repo ${{ github.repository }} --json tagName -q .tagName 2>/dev/null || make version) + else + TAG=$(make version) + fi + echo "TAG=$TAG" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 + uses: aquasecurity/trivy-action@c1824fd6edce30d7ab345a9989de00bbd46ef284 # 0.34.0 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" @@ -39,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: sarif_file: "trivy-results.sarif" diff --git a/.github/workflows/update-hubble.yaml b/.github/workflows/update-hubble.yaml index 0d4ac4dcfd..2e01141c4e 100644 --- a/.github/workflows/update-hubble.yaml +++ b/.github/workflows/update-hubble.yaml @@ -13,6 +13,7 @@ jobs: update-hubble: name: Update Hubble to latest version runs-on: ubuntu-latest + timeout-minutes: 15 steps: - name: Checkout repository @@ -51,7 +52,7 @@ jobs: - name: Create pull request if: env.update_needed == 'true' - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} branch: deps/update-hubble-to-${{ env.version }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml index e015e7ca7b..db214b01b1 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -61,6 +61,12 @@ archives: - goos: windows formats: [ 'zip' ] +checksum: + name_template: 'checksums.txt' + +sboms: + - artifacts: archive + changelog: sort: asc filters: diff --git a/Makefile b/Makefile index 20c5d01a6d..076c0b9990 100644 --- a/Makefile +++ b/Makefile @@ -462,7 +462,7 @@ test: # Run unit tests. coverage: # Code coverage. # go generate ./... && go test -tags=unit -coverprofile=coverage.out.tmp ./... - cat coverage.out | grep -v "_bpf.go\|_bpfel_x86.go\|_bpfel_arm64.go|_generated.go|mock_" | grep -v mock > coveragenew.out + cat coverage.out | grep -Ev '_bpf\.go|_bpfel_x86\.go|_bpfel_arm64\.go|_generated\.go|mock_' > coveragenew.out go tool cover -html coveragenew.out -o coverage.html go tool cover -func=coveragenew.out -o coverageexpanded.out ls -al diff --git a/scripts/coverage/compare_cov.py b/scripts/coverage/compare_cov.py index af48966518..47032a7c34 100644 --- a/scripts/coverage/compare_cov.py +++ b/scripts/coverage/compare_cov.py @@ -9,7 +9,7 @@ pr_num = os.environ.get("PULL_REQUEST_NUMBER") print("PR number is", pr_num) # Set repository information -owner = "azure" +owner = "microsoft" repo = "retina" current_branch_file = "coverageexpanded.out" @@ -42,7 +42,7 @@ def getAvgPerFile(given_dict): # read the current branch coverage file with open(current_branch_file, "r") as f: current_branch_lines = f.readlines() - if current_branch_lines is None: + if not current_branch_lines: print("No coverage data found for current branch") exit(1) for line in current_branch_lines: @@ -74,7 +74,7 @@ def getAvgPerFile(given_dict): # read the main branch coverage file with open(main_branch_file, "r") as f: main_branch_lines = f.readlines() - if main_branch_lines is None: + if not main_branch_lines: print("No coverage data found for main branch") exit(1) for line in main_branch_lines: @@ -266,13 +266,14 @@ def compare_dicts(main_dict, cur_dict): # Make the API call to update the comment update_response = requests.patch(update_url, headers=headers, json=payload) - if update_response.status_code != 200: + if update_response.status_code == 403: + print("Insufficient permissions to update PR comment (expected for fork PRs)") + elif update_response.status_code != 200: print( f"Failed to update the comment with url {update_url}", update_response.content) exit(1) - - # Print the response to confirm that the comment was updated successfully - print(update_response.content) + else: + print("Successfully updated coverage comment on PR") # If there is no existing comment, add a new comment else: @@ -283,10 +284,17 @@ def compare_dicts(main_dict, cur_dict): # Make the API call to add the new comment add_response = requests.post(comments_url, headers=headers, json=payload) - if add_response.status_code != 201: + if add_response.status_code == 403: + print("Insufficient permissions to post PR comment (expected for fork PRs)") + elif add_response.status_code != 201: print( f"Failed to add the comment with url {comments_url}", add_response.content) exit(1) - - # Print the response to confirm that the comment was added successfully - print(add_response.content) + else: + print("Successfully posted coverage comment on PR") + +# Write coverage report to step summary file if available (always visible) +step_summary = os.environ.get("GITHUB_STEP_SUMMARY") +if step_summary: + with open(step_summary, "a") as f: + f.write("\n" + body_of_comment + "\n") diff --git a/scripts/coverage/get_coverage.py b/scripts/coverage/get_coverage.py index d82b304de8..b42b203c0e 100644 --- a/scripts/coverage/get_coverage.py +++ b/scripts/coverage/get_coverage.py @@ -18,10 +18,10 @@ exit(0) # Set repository information -owner = "azure" +owner = "microsoft" repo = "retina" -ut_workflow_yaml = "retina-test.yaml" +ut_workflow_yaml = "test.yaml" # Get the id of UT workflow wf_url = f"https://api.github.com/repos/{owner}/{repo}/actions/workflows/{ut_workflow_yaml}" @@ -34,7 +34,10 @@ params = {"branch": "main", "status": "completed", "per_page": 10} response = requests.get(runs_url, headers=headers, params=params) response.raise_for_status() -artifacts_url = response.json()["workflow_runs"][0]["artifacts_url"] +workflow_runs = response.json()["workflow_runs"] +if not workflow_runs: + print("No completed workflow runs found on main branch") + exit(0) # Create the main branch folder for coverage folder_name = "mainbranchcoverage" @@ -42,7 +45,7 @@ if not os.path.exists(folder_name): os.makedirs(folder_name) -for wf in response.json()["workflow_runs"]: +for wf in workflow_runs: artifacts_url = wf["artifacts_url"] # Get any artifacts named "coverage" for the specified workflow run # artifacts_url = f"https://api.github.com/repos/{owner}/{repo}/actions/runs/{run_id}/artifacts" From 2e370b87d9e4d47080bc2cdef785119243b6ac70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:29:58 -0500 Subject: [PATCH 212/448] deps: bump actions/stale from 10.1.1 to 10.2.0 (#2066) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 10.1.1 to 10.2.0.
Release notes

Sourced from actions/stale's releases.

v10.2.0

What's Changed

Bug Fix

Dependency Updates

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v10...v10.2.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=10.1.1&new-version=10.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index cb6f074313..f52cfed687 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -13,7 +13,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 id: stale with: ascending: true From 7a623cb4a06a7eca92f4d7d544130de20d3dc01d Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 17 Feb 2026 12:07:51 -0500 Subject: [PATCH 213/448] chore(deps): bump pwru to v1.0.11 and hubble to v1.18.6 (#2062) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Bump shell tool versions: - **pwru**: v1.0.9 → v1.0.11 ([release notes](https://github.com/cilium/pwru/releases/tag/v1.0.11)) - **hubble CLI**: v1.18.3 → v1.18.6 ([release notes](https://github.com/cilium/hubble/releases/tag/v1.18.6)) ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed - Verified pwru v1.0.11 release asset URL resolves: `curl -sfIL "https://github.com/cilium/pwru/releases/download/v1.0.11/pwru-linux-amd64.tar.gz"` - Verified hubble v1.18.6 release exists on GitHub Signed-off-by: Quang Nguyen Signed-off-by: Quang Nguyen --- Makefile | 2 +- controller/Dockerfile | 14 +++++++------- shell/Dockerfile | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 076c0b9990..70f120886c 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ PLATFORM ?= $(OS)/$(ARCH) PLATFORMS ?= linux/amd64 linux/arm64 windows/amd64 OS_VERSION ?= ltsc2019 -HUBBLE_VERSION ?= v1.18.3 +HUBBLE_VERSION ?= v1.18.6 CONTAINER_BUILDER ?= docker CONTAINER_RUNTIME ?= docker diff --git a/controller/Dockerfile b/controller/Dockerfile index 9c651af253..534e91765b 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -19,21 +19,21 @@ ARG GOOS=linux # default to linux ENV GOARCH=${GOARCH} ENV GOOS=${GOOS} RUN if [ "$GOOS" = "linux" ] ; then \ - tdnf install -y clang lld bpftool libbpf-devel; \ + tdnf install -y clang lld bpftool libbpf-devel; \ fi COPY ./pkg/plugin /go/src/github.com/microsoft/retina/pkg/plugin WORKDIR /go/src/github.com/microsoft/retina RUN if [ "$GOOS" = "linux" ] ; then \ - go mod init github.com/microsoft/retina; \ - go generate -skip "mockgen" -x /go/src/github.com/microsoft/retina/pkg/plugin/...; \ - tar czf /gen.tar.gz ./pkg/plugin; \ - rm go.mod; \ + go mod init github.com/microsoft/retina; \ + go generate -skip "mockgen" -x /go/src/github.com/microsoft/retina/pkg/plugin/...; \ + tar czf /gen.tar.gz ./pkg/plugin; \ + rm go.mod; \ fi COPY ./go.mod ./go.sum ./ RUN go mod download COPY . . RUN if [ "$GOOS" = "linux" ] ; then \ - rm -rf ./pkg/plugin && tar xvf /gen.tar.gz ./pkg/plugin; \ + rm -rf ./pkg/plugin && tar xvf /gen.tar.gz ./pkg/plugin; \ fi # capture binary @@ -87,7 +87,7 @@ RUN arr="clang tcpdump ip ss iptables-legacy iptables-legacy-save iptables-nft i ARG GOARCH=amd64 ENV HUBBLE_ARCH=${GOARCH} # ARG HUBBLE_VERSION may be modified via the update-hubble GitHub Action -ARG HUBBLE_VERSION=v1.18.3 +ARG HUBBLE_VERSION=v1.18.6 ENV HUBBLE_VERSION=${HUBBLE_VERSION} RUN echo "Hubble version: $HUBBLE_VERSION" && \ wget --no-check-certificate https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz && \ diff --git a/shell/Dockerfile b/shell/Dockerfile index f0ba1541d6..2654eed0aa 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -57,7 +57,7 @@ ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] ARG GOARCH=amd64 ENV ARCH=${GOARCH} # https://github.com/cilium/pwru/releases -ARG PWRU_TAG="v1.0.9" +ARG PWRU_TAG="v1.0.11" ENV PWRU_TAG=${PWRU_TAG} # Download and extract latest pwru release for the correct architecture (amd64 or arm64) From b41e4eeb2315541943021e77dbf1631d71c3045c Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 17 Feb 2026 12:08:01 -0500 Subject: [PATCH 214/448] chore(site): bump dependencies to resolve CVEs (#2063) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Bump all Docusaurus site dependencies to latest compatible versions to resolve 2 high-severity `qs` vulnerabilities. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed - `npm audit` → 0 vulnerabilities - `npm run build` → clean build, no warnings Signed-off-by: Quang Nguyen --- site/docusaurus.config.ts | 8 +- site/package-lock.json | 2415 +++++++++++++++---------------- site/package.json | 32 +- site/site/package-lock.json | 6 - site/src/pages/index.module.css | 77 - 5 files changed, 1222 insertions(+), 1316 deletions(-) delete mode 100644 site/site/package-lock.json diff --git a/site/docusaurus.config.ts b/site/docusaurus.config.ts index 33729a1c61..4c1e8a04cf 100644 --- a/site/docusaurus.config.ts +++ b/site/docusaurus.config.ts @@ -12,7 +12,6 @@ const config = { organizationName: 'Azure', projectName: 'Retina', onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', i18n: { defaultLocale: 'en', @@ -22,6 +21,9 @@ const config = { markdown: { format: "detect", mermaid: true, + hooks: { + onBrokenMarkdownLinks: 'warn', + }, }, plugins: [ @@ -55,12 +57,12 @@ const config = { 'classic', { docs: { - sidebarPath: require.resolve('./sidebars.js'), + sidebarPath: './sidebars.ts', path: '../docs', editUrl: 'https://github.com/microsoft/retina/blob/main/docs', }, theme: { - customCss: require.resolve('./src/css/custom.css'), + customCss: './src/css/custom.css', }, }, ], diff --git a/site/package-lock.json b/site/package-lock.json index 0973ab047c..05452350e9 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -8,111 +8,41 @@ "name": "retina", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.9.1", - "@docusaurus/plugin-ideal-image": "^3.9.1", - "@docusaurus/preset-classic": "^3.9.1", - "@mdx-js/react": "^3.0.0", - "@types/react": "^18.3.7", - "clsx": "^2.0.0", - "docusaurus-lunr-search": "^3.5.0", + "@docusaurus/core": "^3.9.2", + "@docusaurus/plugin-ideal-image": "^3.9.2", + "@docusaurus/preset-classic": "^3.9.2", + "@mdx-js/react": "^3.1.1", + "@types/react": "^18.3.28", + "clsx": "^2.1.1", + "docusaurus-lunr-search": "^3.6.0", "micromatch": "^4.0.8", - "prism-react-renderer": "^2.3.1", + "prism-react-renderer": "^2.4.1", "react": "^18.3.1", - "react-dom": "^18.2.0", + "react-dom": "^18.3.1", "sharp": "^0.33.5" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.8.0", - "@docusaurus/tsconfig": "^3.8.0", - "@docusaurus/types": "^3.8.0", + "@docusaurus/module-type-aliases": "^3.9.2", + "@docusaurus/tsconfig": "^3.9.2", + "@docusaurus/types": "^3.9.2", "css-loader": "^7.1.2", "style-loader": "^4.0.0", - "typescript": "^5.6.2" - }, - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@ai-sdk/gateway": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-1.0.39.tgz", - "integrity": "sha512-ijYCKG2sbn2RBVfIgaXNXvzHAf2HpFXxQODtjMI+T7Z4CLryflytchsZZ9qrGtsjiQVopKOV6m6kj4lq5fnbsg==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.12", - "@vercel/oidc": "3.0.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", - "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" + "typescript": "^5.7.3" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.12.tgz", - "integrity": "sha512-ZtbdvYxdMoria+2SlNarEk6Hlgyf+zzcznlD55EAl+7VZvJaSg2sqPvwArY7L6TfDEDJsnCq0fdhBSkYo0Xqdg==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@standard-schema/spec": "^1.0.0", - "eventsource-parser": "^3.0.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/react": { - "version": "2.0.68", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.68.tgz", - "integrity": "sha512-dj21puWzGsNNrDE/26cytapMlS2/LD5NiN8TrU59fU/FVwuFHjwiepSfscBik54t/xNYRQIU+Qvt7lM7jnXJdg==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider-utils": "3.0.12", - "ai": "5.0.68", - "swr": "^2.2.5", - "throttleit": "2.1.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "zod": "^3.25.76 || ^4.1.8" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } + "node": ">=18.0.0" } }, "node_modules/@algolia/abtesting": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.6.0.tgz", - "integrity": "sha512-c4M/Z/KWkEG+RHpZsWKDTTlApXu3fe4vlABNcpankWBhdMe4oPZ/r4JxEr2zKUP6K+BT66tnp8UbHmgOd/vvqQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.14.1.tgz", + "integrity": "sha512-Dkj0BgPiLAaim9sbQ97UKDFHJE/880wgStAM18U++NaJ/2Cws34J5731ovJifr6E3Pv4T2CqvMXf8qLCC417Ew==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" @@ -151,99 +81,99 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.40.0.tgz", - "integrity": "sha512-qegVlgHtmiS8m9nEsuKUVhlw1FHsIshtt5nhNnA6EYz3g+tm9+xkVZZMzkrMLPP7kpoheHJZAwz2MYnHtwFa9A==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.48.1.tgz", + "integrity": "sha512-LV5qCJdj+/m9I+Aj91o+glYszrzd7CX6NgKaYdTOj4+tUYfbS62pwYgUfZprYNayhkQpVFcrW8x8ZlIHpS23Vw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.40.0.tgz", - "integrity": "sha512-Dw2c+6KGkw7mucnnxPyyMsIGEY8+hqv6oB+viYB612OMM3l8aNaWToBZMnNvXsyP+fArwq7XGR+k3boPZyV53A==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.48.1.tgz", + "integrity": "sha512-/AVoMqHhPm14CcHq7mwB+bUJbfCv+jrxlNvRjXAuO+TQa+V37N8k1b0ijaRBPdmSjULMd8KtJbQyUyabXOu6Kg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.40.0.tgz", - "integrity": "sha512-dbE4+MJIDsTghG3hUYWBq7THhaAmqNqvW9g2vzwPf5edU4IRmuYpKtY3MMotes8/wdTasWG07XoaVhplJBlvdg==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.48.1.tgz", + "integrity": "sha512-VXO+qu2Ep6ota28ktvBm3sG53wUHS2n7bgLWmce5jTskdlCD0/JrV4tnBm1l7qpla1CeoQb8D7ShFhad+UoSOw==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.40.0.tgz", - "integrity": "sha512-SH6zlROyGUCDDWg71DlCnbbZ/zEHYPZC8k901EAaBVhvY43Ju8Wa6LAcMPC4tahcDBgkG2poBy8nJZXvwEWAlQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.48.1.tgz", + "integrity": "sha512-zl+Qyb0nLg+Y5YvKp1Ij+u9OaPaKg2/EPzTwKNiVyOHnQJlFxmXyUZL1EInczAZsEY8hVpPCLtNfhMhfxluXKQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.40.0.tgz", - "integrity": "sha512-EgHjJEEf7CbUL9gJHI1ULmAtAFeym2cFNSAi1uwHelWgLPcnLjYW2opruPxigOV7NcetkGu+t2pcWOWmZFuvKQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.48.1.tgz", + "integrity": "sha512-r89Qf9Oo9mKWQXumRu/1LtvVJAmEDpn8mHZMc485pRfQUMAwSSrsnaw1tQ3sszqzEgAr1c7rw6fjBI+zrAXTOw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.40.0.tgz", - "integrity": "sha512-HvE1jtCag95DR41tDh7cGwrMk4X0aQXPOBIhZRmsBPolMeqRJz0kvfVw8VCKvA1uuoAkjFfTG0X0IZED+rKXoA==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.48.1.tgz", + "integrity": "sha512-TPKNPKfghKG/bMSc7mQYD9HxHRUkBZA4q1PEmHgICaSeHQscGqL4wBrKkhfPlDV1uYBKW02pbFMUhsOt7p4ZpA==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.0.tgz", - "integrity": "sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", + "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" @@ -256,93 +186,93 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.40.0.tgz", - "integrity": "sha512-OfHnhE+P0f+p3i90Kmshf9Epgesw5oPV1IEUOY4Mq1HV7cQk16gvklVN1EaY/T9sVavl+Vc3g4ojlfpIwZFA4g==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.48.1.tgz", + "integrity": "sha512-/RFq3TqtXDUUawwic/A9xylA2P3LDMO8dNhphHAUOU51b1ZLHrmZ6YYJm3df1APz7xLY1aht6okCQf+/vmrV9w==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.40.0.tgz", - "integrity": "sha512-SWANV32PTKhBYvwKozeWP9HOnVabOixAuPdFFGoqtysTkkwutrtGI/rrh80tvG+BnQAmZX0vUmD/RqFZVfr/Yg==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.48.1.tgz", + "integrity": "sha512-Of0jTeAZRyRhC7XzDSjJef0aBkgRcvRAaw0ooYRlOw57APii7lZdq+layuNdeL72BRq1snaJhoMMwkmLIpJScw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.40.0.tgz", - "integrity": "sha512-1Qxy9I5bSb3mrhPk809DllMa561zl5hLsMR6YhIqNkqQ0OyXXQokvJ2zApSxvd39veRZZnhN+oGe+XNoNwLgkw==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.48.1.tgz", + "integrity": "sha512-bE7JcpFXzxF5zHwj/vkl2eiCBvyR1zQ7aoUdO+GDXxGp0DGw7nI0p8Xj6u8VmRQ+RDuPcICFQcCwRIJT5tDJFw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "@algolia/client-common": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.40.0.tgz", - "integrity": "sha512-MGt94rdHfkrVjfN/KwUfWcnaeohYbWGINrPs96f5J7ZyRYpVLF+VtPQ2FmcddFvK4gnKXSu8BAi81hiIhUpm3w==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.48.1.tgz", + "integrity": "sha512-MK3wZ2koLDnvH/AmqIF1EKbJlhRS5j74OZGkLpxI4rYvNi9Jn/C7vb5DytBnQ4KUWts7QsmbdwHkxY5txQHXVw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0" + "@algolia/client-common": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.40.0.tgz", - "integrity": "sha512-wXQ05JZZ10Dr642QVAkAZ4ZZlU+lh5r6dIBGmm9WElz+1EaQ6BNYtEOTV6pkXuFYsZpeJA89JpDOiwBOP9j24w==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.48.1.tgz", + "integrity": "sha512-2oDT43Y5HWRSIQMPQI4tA/W+TN/N2tjggZCUsqQV440kxzzoPGsvv9QP1GhQ4CoDa+yn6ygUsGp6Dr+a9sPPSg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0" + "@algolia/client-common": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.40.0.tgz", - "integrity": "sha512-5qCRoySnzpbQVg2IPLGFCm4LF75pToxI5tdjOYgUMNL/um91aJ4dH3SVdBEuFlVsalxl8mh3bWPgkUmv6NpJiQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.48.1.tgz", + "integrity": "sha512-xcaCqbhupVWhuBP1nwbk1XNvwrGljozutEiLx06mvqDf3o8cHyEgQSHS4fKJM+UAggaWVnnFW+Nne5aQ8SUJXg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.40.0" + "@algolia/client-common": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -351,29 +281,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -399,13 +329,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -427,12 +357,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -452,17 +382,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", - "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.3", + "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "engines": { @@ -482,13 +412,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", - "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "regexpu-core": "^6.2.0", + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "engines": { @@ -508,16 +438,16 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", + "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -533,40 +463,40 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -588,9 +518,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -614,14 +544,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -653,9 +583,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -671,39 +601,39 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", - "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", + "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2" + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -713,13 +643,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -776,13 +706,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", - "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -816,12 +746,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", + "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -831,12 +761,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -846,12 +776,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -861,12 +791,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -907,14 +837,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", - "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", + "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.29.0" }, "engines": { "node": ">=6.9.0" @@ -924,13 +854,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", + "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { @@ -956,12 +886,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.4.tgz", - "integrity": "sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", + "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -971,13 +901,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -987,13 +917,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", - "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", + "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1003,17 +933,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", - "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", + "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.4" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1023,13 +953,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", + "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/template": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/template": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1039,13 +969,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", - "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1055,13 +985,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", + "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1086,13 +1016,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1117,13 +1047,13 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", - "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1133,12 +1063,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", + "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1196,12 +1126,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", + "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1226,12 +1156,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", + "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1272,13 +1202,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1288,15 +1218,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", + "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.29.0" }, "engines": { "node": ">=6.9.0" @@ -1322,13 +1252,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1353,12 +1283,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1368,12 +1298,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", + "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1383,16 +1313,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", - "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", + "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.4" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1418,12 +1348,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", + "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1433,12 +1363,12 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { @@ -1464,13 +1394,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1480,14 +1410,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", + "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1542,16 +1472,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz", + "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-jsx": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1592,12 +1522,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", - "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", + "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1607,13 +1537,13 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1638,13 +1568,13 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", - "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz", + "integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", @@ -1682,12 +1612,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", + "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { @@ -1743,16 +1673,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", - "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" + "@babel/plugin-syntax-typescript": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1777,13 +1707,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", + "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1809,13 +1739,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", + "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1825,80 +1755,80 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", - "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", + "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/compat-data": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.0", - "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.29.0", + "@babel/plugin-transform-async-to-generator": "^7.28.6", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.0", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.28.3", - "@babel/plugin-transform-classes": "^7.28.3", - "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", - "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.28.6", "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.0", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", "@babel/plugin-transform-member-expression-literals": "^7.27.1", "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", + "@babel/plugin-transform-modules-systemjs": "^7.29.0", "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.28.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.3", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.29.0", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", "@babel/plugin-transform-sticky-regex": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-typeof-symbol": "^7.27.1", "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1908,6 +1838,19 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", + "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.6", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1932,14 +1875,14 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz", - "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" @@ -1952,16 +1895,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", - "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-typescript": "^7.27.1" + "@babel/plugin-transform-typescript": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1983,43 +1926,43 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz", - "integrity": "sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.0.tgz", + "integrity": "sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA==", "license": "MIT", "dependencies": { - "core-js-pure": "^3.43.0" + "core-js-pure": "^3.48.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", "debug": "^4.3.1" }, "engines": { @@ -2027,13 +1970,13 @@ } }, "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -2282,9 +2225,9 @@ } }, "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -2703,9 +2646,9 @@ } }, "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -2942,9 +2885,9 @@ } }, "node_modules/@csstools/postcss-normalize-display-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz", - "integrity": "sha512-HlEoG0IDRoHXzXnkV4in47dzsxdsjdz6+j7MLjaACABX2NfvjFS6XVAnpaDyGesz9gK2SC7MbNwdCHusObKJ9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz", + "integrity": "sha512-TQUGBuRvxdc7TgNSTevYqrL8oItxiwPDixk20qCB5me/W8uF7BPbhRrAvFuhEoywQp/woRsUZ6SJ+sU5idZAIA==", "funding": [ { "type": "github", @@ -2995,6 +2938,28 @@ "postcss": "^8.4" } }, + "node_modules/@csstools/postcss-position-area-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-position-area-property/-/postcss-position-area-property-1.0.0.tgz", + "integrity": "sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-progressive-custom-properties": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.2.1.tgz", @@ -3020,6 +2985,32 @@ "postcss": "^8.4" } }, + "node_modules/@csstools/postcss-property-rule-prelude-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-property-rule-prelude-list/-/postcss-property-rule-prelude-list-1.0.0.tgz", + "integrity": "sha512-IxuQjUXq19fobgmSSvUDO7fVwijDJaZMvWQugxfEUxmjBeDCVaDuMpsZ31MsTm5xbnhA+ElDi0+rQ7sQQGisFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-random-function": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-2.0.1.tgz", @@ -3102,9 +3093,9 @@ } }, "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -3168,6 +3159,57 @@ "postcss": "^8.4" } }, + "node_modules/@csstools/postcss-syntax-descriptor-syntax-production": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-syntax-descriptor-syntax-production/-/postcss-syntax-descriptor-syntax-production-1.0.1.tgz", + "integrity": "sha512-GneqQWefjM//f4hJ/Kbox0C6f2T7+pi4/fqTqOFGTL3EjnvOReTqO1qUQ30CaUjkwjYq9qZ41hzarrAxCc4gow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-system-ui-font-family": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-system-ui-font-family/-/postcss-system-ui-font-family-1.0.0.tgz", + "integrity": "sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/postcss-text-decoration-shorthand": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.3.tgz", @@ -3274,25 +3316,43 @@ "node": ">=10.0.0" } }, + "node_modules/@docsearch/core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.5.4.tgz", + "integrity": "sha512-DbkfZbJyYAPFJtF71eAFOTQSy5z5c/hdSN0UrErORKDwXKLTJBR0c+5WxE5l+IKZx4xIaEa8RkrL7T28DTCOYw==", + "license": "MIT", + "peerDependencies": { + "@types/react": ">= 16.8.0 < 20.0.0", + "react": ">= 16.8.0 < 20.0.0", + "react-dom": ">= 16.8.0 < 20.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@docsearch/css": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.2.0.tgz", - "integrity": "sha512-65KU9Fw5fGsPPPlgIghonMcndyx1bszzrDQYLfierN+Ha29yotMHzVS94bPkZS6On9LS8dE4qmW4P/fGjtCf/g==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.5.4.tgz", + "integrity": "sha512-gzO4DJwyM9c4YEPHwaLV1nUCDC2N6yoh0QJj44dce2rcfN71mB+jpu3+F+Y/KMDF1EKV0C3m54leSWsraE94xg==", "license": "MIT" }, "node_modules/@docsearch/react": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.2.0.tgz", - "integrity": "sha512-zSN/KblmtBcerf7Z87yuKIHZQmxuXvYc6/m0+qnjyNu+Ir67AVOagTa1zBqcxkVUVkmBqUExdcyrdo9hbGbqTw==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.5.4.tgz", + "integrity": "sha512-iBNFfvWoUFRUJmGQ/r+0AEp2OJgJMoYIKRiRcTDON0hObBRSLlrv2ktb7w3nc1MeNm1JIpbPA99i59TiIR49fA==", "license": "MIT", "dependencies": { - "@ai-sdk/react": "^2.0.30", "@algolia/autocomplete-core": "1.19.2", - "@docsearch/css": "4.2.0", - "ai": "^5.0.30", - "algoliasearch": "^5.28.0", - "marked": "^16.3.0", - "zod": "^4.1.8" + "@docsearch/core": "4.5.4", + "@docsearch/css": "4.5.4" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", @@ -3316,9 +3376,9 @@ } }, "node_modules/@docusaurus/babel": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.1.tgz", - "integrity": "sha512-/uoi3oG+wvbVWNBRfPrzrEslOSeLxrQEyWMywK51TLDFTANqIRivzkMusudh5bdDty8fXzCYUT+tg5t697jYqg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", + "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3331,8 +3391,8 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.9.1", - "@docusaurus/utils": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3342,17 +3402,17 @@ } }, "node_modules/@docusaurus/bundler": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.1.tgz", - "integrity": "sha512-E1c9DgNmAz4NqbNtiJVp4UgjLtr8O01IgtXD/NDQ4PZaK8895cMiTOgb3k7mN0qX8A3lb8vqyrPJ842+yMpuUg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", + "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.9.1", - "@docusaurus/cssnano-preset": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", + "@docusaurus/babel": "3.9.2", + "@docusaurus/cssnano-preset": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", @@ -3420,18 +3480,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.1.tgz", - "integrity": "sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.9.1", - "@docusaurus/bundler": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", + "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.9.2", + "@docusaurus/bundler": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3495,9 +3555,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.1.tgz", - "integrity": "sha512-2y7+s7RWQMqBg+9ejeKwvZs7Bdw/hHIVJIodwMXbs2kr+S48AhcmAfdOh6Cwm0unJb0hJUshN0ROwRoQMwl3xg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", + "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", @@ -3510,9 +3570,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.1.tgz", - "integrity": "sha512-C9iFzXwHzwvGlisE4bZx+XQE0JIqlGAYAd5LzpR7fEDgjctu7yL8bE5U4nTNywXKHURDzMt4RJK8V6+stFHVkA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", + "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -3523,12 +3583,12 @@ } }, "node_modules/@docusaurus/lqip-loader": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.9.1.tgz", - "integrity": "sha512-bCYHDxZ9U0M9pUdbUyrqyOmTuDZQw4MhZOdib+MZPmcor8U2spHnPW9+fagzJfmyoZ321X/tvEDSo3g+UxSM1Q==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.9.2.tgz", + "integrity": "sha512-Q9QO0E+HLKhcpKVOIXRVBdJ1bbxxpfSwBll5NsmGxcx1fArH0fFi68cpEztqBg7WwbFRb976MTlqlBuGrMLpuw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", + "@docusaurus/logger": "3.9.2", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", @@ -3562,14 +3622,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.1.tgz", - "integrity": "sha512-/1PY8lqry8jCt0qZddJSpc0U2sH6XC27kVJZfpA7o2TiQ3mdBQyH5AVbj/B2m682B1ounE+XjI0LdpOkAQLPoA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", + "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -3601,12 +3661,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.1.tgz", - "integrity": "sha512-YBce3GbJGGcMbJTyHcnEOMvdXqg41pa5HsrMCGA5Rm4z0h0tHS6YtEldj0mlfQRhCG7Y0VD66t2tb87Aom+11g==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz", + "integrity": "sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.1", + "@docusaurus/types": "3.9.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3620,19 +3680,19 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.1.tgz", - "integrity": "sha512-vT6kIimpJLWvW9iuWzH4u7VpTdsGlmn4yfyhq0/Kb1h4kf9uVouGsTmrD7WgtYBUG1P+TSmQzUUQa+ALBSRTig==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz", + "integrity": "sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -3654,20 +3714,20 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", - "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", + "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -3687,16 +3747,16 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.1.tgz", - "integrity": "sha512-/1wFzRnXYASI+Nv9ck9IVPIMw0O5BGQ8ZVhDzEwhkL+tl44ycvSnY6PIe6rW2HLxsw61Z3WFwAiU8+xMMtMZpg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz", + "integrity": "sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -3710,15 +3770,15 @@ } }, "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.1.tgz", - "integrity": "sha512-/QyW2gRCk/XE3ttCK/ERIgle8KJ024dBNKMu6U5SmpJvuT2il1n5jR/48Pp/9wEwut8WVml4imNm6X8JsL5A0Q==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz", + "integrity": "sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -3726,14 +3786,14 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.1.tgz", - "integrity": "sha512-qPeAuk0LccC251d7jg2MRhNI+o7niyqa924oEM/AxnZJvIpMa596aAxkRImiAqNN6+gtLE1Hkrz/RHUH2HDGsA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz", + "integrity": "sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", "fs-extra": "^11.1.1", "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" @@ -3747,14 +3807,14 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.1.tgz", - "integrity": "sha512-k4Qq2HphqOrIU/CevGPdEO1yJnWUI8m0zOJsYt5NfMJwNsIn/gDD6gv/DKD+hxHndQT5pacsfBd4BWHZVNVroQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz", + "integrity": "sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -3766,14 +3826,14 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.1.tgz", - "integrity": "sha512-n9BURBiQyJKI/Ecz35IUjXYwXcgNCSq7/eA07+ZYcDiSyH2p/EjPf8q/QcZG3CyEJPZ/SzGkDHePfcVPahY4Gg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz", + "integrity": "sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -3786,14 +3846,14 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.1.tgz", - "integrity": "sha512-rZAQZ25ZuXaThBajxzLjXieTDUCMmBzfAA6ThElQ3o7Q+LEpOjCIrwGFau0KLY9HeG6x91+FwwsAM8zeApYDrg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz", + "integrity": "sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -3805,17 +3865,17 @@ } }, "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.1.tgz", - "integrity": "sha512-9d4VKG/jSQj4sf9wKYpr+5q4wPOnEAqGAMcLLvuh+LXmCPmrKwMOrr9M0ycCaYdE0eL/uOrLhVa5E1H2MuTEvA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.2.tgz", + "integrity": "sha512-YYYbmC2wSYFd7o4//5rPXt9+DkZwfwjCUmyGi5OIVqEbwELK80o3COXs2Xd0BtVIpuRvG7pKCYrMQwVo32Y9qw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/lqip-loader": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/lqip-loader": "3.9.2", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "sharp": "^0.32.3", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -3857,17 +3917,17 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.1.tgz", - "integrity": "sha512-k/bf5cXDxAJUYTzqatgFJwmZsLUbIgl6S8AdZMKGG2Mv2wcOHt+EQNN9qPyWZ5/9cFj+Q8f8DN+KQheBMYLong==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz", + "integrity": "sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -3881,15 +3941,15 @@ } }, "node_modules/@docusaurus/plugin-svgr": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.1.tgz", - "integrity": "sha512-TeZOXT2PSdTNR1OpDJMkYqFyX7MMhbd4t16hQByXksgZQCXNyw3Dio+KaDJ2Nj+LA4WkOvsk45bWgYG5MAaXSQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz", + "integrity": "sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", @@ -3904,26 +3964,26 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.1.tgz", - "integrity": "sha512-ZHga2xsxxsyd0dN1BpLj8S889Eu9eMBuj2suqxdw/vaaXu/FjJ8KEGbcaeo6nHPo8VQcBBnPEdkBtSDm2TfMNw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/plugin-content-blog": "3.9.1", - "@docusaurus/plugin-content-docs": "3.9.1", - "@docusaurus/plugin-content-pages": "3.9.1", - "@docusaurus/plugin-css-cascade-layers": "3.9.1", - "@docusaurus/plugin-debug": "3.9.1", - "@docusaurus/plugin-google-analytics": "3.9.1", - "@docusaurus/plugin-google-gtag": "3.9.1", - "@docusaurus/plugin-google-tag-manager": "3.9.1", - "@docusaurus/plugin-sitemap": "3.9.1", - "@docusaurus/plugin-svgr": "3.9.1", - "@docusaurus/theme-classic": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/theme-search-algolia": "3.9.1", - "@docusaurus/types": "3.9.1" + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz", + "integrity": "sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/plugin-content-blog": "3.9.2", + "@docusaurus/plugin-content-docs": "3.9.2", + "@docusaurus/plugin-content-pages": "3.9.2", + "@docusaurus/plugin-css-cascade-layers": "3.9.2", + "@docusaurus/plugin-debug": "3.9.2", + "@docusaurus/plugin-google-analytics": "3.9.2", + "@docusaurus/plugin-google-gtag": "3.9.2", + "@docusaurus/plugin-google-tag-manager": "3.9.2", + "@docusaurus/plugin-sitemap": "3.9.2", + "@docusaurus/plugin-svgr": "3.9.2", + "@docusaurus/theme-classic": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/theme-search-algolia": "3.9.2", + "@docusaurus/types": "3.9.2" }, "engines": { "node": ">=20.0" @@ -3957,24 +4017,24 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.1.tgz", - "integrity": "sha512-LrAIu/mQ04nG6s1cssC0TMmICD8twFIIn/hJ5Pd9uIPQvtKnyAKEn12RefopAul5KfMo9kixPaqogV5jIJr26w==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/plugin-content-blog": "3.9.1", - "@docusaurus/plugin-content-docs": "3.9.1", - "@docusaurus/plugin-content-pages": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/theme-translations": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz", + "integrity": "sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/plugin-content-blog": "3.9.2", + "@docusaurus/plugin-content-docs": "3.9.2", + "@docusaurus/plugin-content-pages": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "infima": "0.2.0-alpha.45", @@ -3997,15 +4057,15 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.1.tgz", - "integrity": "sha512-j9adi961F+6Ps9d0jcb5BokMcbjXAAJqKkV43eo8nh4YgmDj7KUNDX4EnOh/MjTQeO06oPY5cxp3yUXdW/8Ggw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.2.tgz", + "integrity": "sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -4025,19 +4085,19 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.1.tgz", - "integrity": "sha512-WjM28bzlgfT6nHlEJemkwyGVpvGsZWPireV/w+wZ1Uo64xCZ8lNOb4xwQRukDaLSed3oPBN0gSnu06l5VuCXHg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz", + "integrity": "sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw==", "license": "MIT", "dependencies": { "@docsearch/react": "^3.9.0 || ^4.1.0", - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/plugin-content-docs": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/theme-translations": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/plugin-content-docs": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "algoliasearch": "^5.37.0", "algoliasearch-helper": "^3.26.0", "clsx": "^2.0.0", @@ -4056,9 +4116,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.1.tgz", - "integrity": "sha512-mUQd49BSGKTiM6vP9+JFgRJL28lMIN3PUvXjF3rzuOHMByUZUBNwCt26Z23GkKiSIOrRkjKoaBNTipR/MHdYSQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz", + "integrity": "sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", @@ -4069,16 +4129,16 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.8.0.tgz", - "integrity": "sha512-utLl48nNjSYBoq47RKukZ9fPLEX3nJWThzrujb0ndQQ1jc/gh4RhTRaAqItH9nImnsgGKmLMnyoMBpfGmoop+w==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.9.2.tgz", + "integrity": "sha512-j6/Fp4Rlpxsc632cnRnl5HpOWeb6ZKssDj6/XzzAzVGXXfm9Eptx3rxCC+fDzySn9fHTS+CWJjPineCR1bB5WQ==", "dev": true, "license": "MIT" }, "node_modules/@docusaurus/types": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.1.tgz", - "integrity": "sha512-ElekJ29sk39s5LTEZMByY1c2oH9FMtw7KbWFU3BtuQ1TytfIK39HhUivDEJvm5KCLyEnnfUZlvSNDXeyk0vzAA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", @@ -4098,14 +4158,14 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.1.tgz", - "integrity": "sha512-YAL4yhhWLl9DXuf5MVig260a6INz4MehrBGFU/CZu8yXmRiYEuQvRFWh9ZsjfAOyaG7za1MNmBVZ4VVAi/CiJA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.2.tgz", + "integrity": "sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-common": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-common": "3.9.2", "escape-string-regexp": "^4.0.0", "execa": "5.1.1", "file-loader": "^6.2.0", @@ -4130,12 +4190,12 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.1.tgz", - "integrity": "sha512-4M1u5Q8Zn2CYL2TJ864M51FV4YlxyGyfC3x+7CLuR6xsyTVNBNU4QMcPgsTHRS9J2+X6Lq7MyH6hiWXyi/sXUQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.2.tgz", + "integrity": "sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.1", + "@docusaurus/types": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -4143,14 +4203,14 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.1.tgz", - "integrity": "sha512-5bzab5si3E1udrlZuVGR17857Lfwe8iFPoy5AvMP9PXqDfoyIKT7gDQgAmxdRDMurgHaJlyhXEHHdzDKkOxxZQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz", + "integrity": "sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -4729,15 +4789,16 @@ "license": "MIT" }, "node_modules/@mdx-js/mdx": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", - "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", @@ -4765,9 +4826,10 @@ } }, "node_modules/@mdx-js/react": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.0.tgz", - "integrity": "sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", + "license": "MIT", "dependencies": { "@types/mdx": "^2.0.0" }, @@ -4815,15 +4877,6 @@ "node": ">= 8" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -4889,9 +4942,9 @@ "license": "BSD-3-Clause" }, "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", "license": "MIT" }, "node_modules/@sindresorhus/is": { @@ -4917,12 +4970,6 @@ "micromark-util-symbol": "^1.0.1" } }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT" - }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -5429,9 +5476,10 @@ "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, "node_modules/@types/prismjs": { - "version": "1.26.3", - "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", - "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" + "version": "1.26.6", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz", + "integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==", + "license": "MIT" }, "node_modules/@types/prop-types": { "version": "15.7.11", @@ -5451,13 +5499,13 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.7.tgz", - "integrity": "sha512-KUnDCJF5+AiZd8owLIeVHqmW9yM4sqmDVf2JRJiBMFkGvkoZ4/WyV2lL4zVsoinmRS/W3FeEdZLEWFRofnT2FQ==", + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", "dependencies": { "@types/prop-types": "*", - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-router": { @@ -5568,9 +5616,9 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "license": "MIT", "dependencies": { "@types/yargs-parser": "*" @@ -5588,15 +5636,6 @@ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, - "node_modules/@vercel/oidc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.2.tgz", - "integrity": "sha512-JekxQ0RApo4gS4un/iMGsIL1/k4KUBe3HmnGcDvzHuFBdQdudEJgTqcsJC7y6Ul4Yw5CeykgvQbX2XeEJd0+DA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 20" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -5869,24 +5908,6 @@ "node": ">=8" } }, - "node_modules/ai": { - "version": "5.0.68", - "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.68.tgz", - "integrity": "sha512-SB6r+4TkKVlSg2ozGBSfuf6Is5hrcX/bpGBzOoyHIN3b4ILGhaly0IHEvP8+3GGIHXqtkPVEUmR6V05jKdjNlg==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/gateway": "1.0.39", - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.12", - "@opentelemetry/api": "1.9.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -5933,34 +5954,34 @@ } }, "node_modules/algoliasearch": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.0.tgz", - "integrity": "sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==", - "license": "MIT", - "dependencies": { - "@algolia/abtesting": "1.6.0", - "@algolia/client-abtesting": "5.40.0", - "@algolia/client-analytics": "5.40.0", - "@algolia/client-common": "5.40.0", - "@algolia/client-insights": "5.40.0", - "@algolia/client-personalization": "5.40.0", - "@algolia/client-query-suggestions": "5.40.0", - "@algolia/client-search": "5.40.0", - "@algolia/ingestion": "1.40.0", - "@algolia/monitoring": "1.40.0", - "@algolia/recommend": "5.40.0", - "@algolia/requester-browser-xhr": "5.40.0", - "@algolia/requester-fetch": "5.40.0", - "@algolia/requester-node-http": "5.40.0" + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", + "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.14.1", + "@algolia/client-abtesting": "5.48.1", + "@algolia/client-analytics": "5.48.1", + "@algolia/client-common": "5.48.1", + "@algolia/client-insights": "5.48.1", + "@algolia/client-personalization": "5.48.1", + "@algolia/client-query-suggestions": "5.48.1", + "@algolia/client-search": "5.48.1", + "@algolia/ingestion": "1.48.1", + "@algolia/monitoring": "1.48.1", + "@algolia/recommend": "5.48.1", + "@algolia/requester-browser-xhr": "5.48.1", + "@algolia/requester-fetch": "5.48.1", + "@algolia/requester-node-http": "5.48.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.26.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz", - "integrity": "sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==", + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.27.1.tgz", + "integrity": "sha512-XXGr02Cz285vLbqM6vPfb39xqV1ptpFr1xn9mqaW+nUvYTvFTdKgYTC/Cg1VzgRTQqNkq9+LlUVv8cfCeOoKig==", "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" @@ -6119,9 +6140,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "version": "10.4.24", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz", + "integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==", "funding": [ { "type": "opencollective", @@ -6138,10 +6159,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001766", + "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, @@ -6187,13 +6207,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", + "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.6", "semver": "^6.3.1" }, "peerDependencies": { @@ -6223,12 +6243,12 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", + "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.6" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -6395,23 +6415,23 @@ } }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -6436,12 +6456,41 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/bonjour-service": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", @@ -6998,9 +7047,10 @@ } }, "node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -7339,12 +7389,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.46.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", - "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", + "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", "license": "MIT", "dependencies": { - "browserslist": "^4.26.3" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -7352,9 +7402,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.46.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.46.0.tgz", - "integrity": "sha512-NMCW30bHNofuhwLhYPt66OLOKTMbOhgTTatKVbaQC3KRHpTCiRIBYvtshr+NBYSnBxwAFhjW/RfJ0XbIjS16rw==", + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.48.0.tgz", + "integrity": "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -7458,9 +7508,9 @@ } }, "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -7471,9 +7521,9 @@ } }, "node_modules/css-declaration-sorter": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.3.0.tgz", - "integrity": "sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.3.1.tgz", + "integrity": "sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==", "license": "ISC", "engines": { "node": "^14 || ^16 || >=18" @@ -7532,9 +7582,9 @@ } }, "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -7691,9 +7741,9 @@ } }, "node_modules/cssdb": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.4.2.tgz", - "integrity": "sha512-PzjkRkRUS+IHDJohtxkIczlxPPZqRo0nXplsYXOMBRPjcVRjj1W4DfvRgshUYTVuUigU7ptVYkFJQ7abUB0nyg==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.7.1.tgz", + "integrity": "sha512-+F6LKx48RrdGOtE4DT5jz7Uo+VeyKXpK797FAevIkzjV8bMHz6xTO5F7gNDcRCHmPgD5jj2g6QCsY9zmVrh38A==", "funding": [ { "type": "opencollective", @@ -7848,9 +7898,10 @@ "license": "CC0-1.0" }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" }, "node_modules/debounce": { "version": "1.2.1", @@ -7876,9 +7927,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", - "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -8114,32 +8165,33 @@ } }, "node_modules/docusaurus-lunr-search": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/docusaurus-lunr-search/-/docusaurus-lunr-search-3.5.0.tgz", - "integrity": "sha512-k3zN4jYMi/prWInJILGKOxE+BVcgYinwj9+gcECsYm52tS+4ZKzXQzbPnVJAEXmvKOfFMcDFvS3MSmm6cEaxIQ==", - "dependencies": { - "autocomplete.js": "^0.37.0", - "clsx": "^1.2.1", - "gauge": "^3.0.0", - "hast-util-select": "^4.0.0", - "hast-util-to-text": "^2.0.0", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/docusaurus-lunr-search/-/docusaurus-lunr-search-3.6.0.tgz", + "integrity": "sha512-CCEAnj5e67sUZmIb2hOl4xb4nDN07fb0fvRDDmdWlYpUvyS1CSKbw4lsGInLyUFEEEBzxQmT6zaVQdF/8Zretg==", + "license": "MIT", + "dependencies": { + "autocomplete.js": "^0.37.1", + "clsx": "^2.1.1", + "gauge": "^3.0.2", + "hast-util-select": "^4.0.2", + "hast-util-to-text": "^2.0.1", "hogan.js": "^3.0.2", - "lunr": "^2.3.8", + "lunr": "^2.3.9", "lunr-languages": "^1.4.0", "mark.js": "^8.11.1", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "rehype-parse": "^7.0.1", "to-vfile": "^6.1.0", - "unified": "^9.0.0", - "unist-util-is": "^4.0.2" + "unified": "^9.2.2", + "unist-util-is": "^4.1.0" }, "engines": { "node": ">= 8.10.0" }, "peerDependencies": { "@docusaurus/core": "^2.0.0-alpha.60 || ^2.0.0 || ^3.0.0", - "react": "^16.8.4 || ^17 || ^18", - "react-dom": "^16.8.4 || ^17 || ^18" + "react": "^16.8.4 || ^17 || ^18 || ^19", + "react-dom": "^16.8.4 || ^17 || ^18 || ^19" } }, "node_modules/docusaurus-lunr-search/node_modules/@types/unist": { @@ -8156,14 +8208,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/docusaurus-lunr-search/node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "engines": { - "node": ">=6" - } - }, "node_modules/docusaurus-lunr-search/node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -8681,9 +8725,9 @@ } }, "node_modules/estree-util-value-to-estree": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.0.tgz", - "integrity": "sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.5.0.tgz", + "integrity": "sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -8770,15 +8814,6 @@ "node": ">=0.8.x" } }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -8901,21 +8936,6 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, - "node_modules/express/node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8972,7 +8992,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" }, "node_modules/fast-uri": { "version": "3.1.0", @@ -8991,9 +9012,9 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -9233,14 +9254,6 @@ } } }, - "node_modules/form-data-encoder": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz", - "integrity": "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==", - "engines": { - "node": ">= 18" - } - }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -9259,15 +9272,15 @@ } }, "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", "license": "MIT", "engines": { "node": "*" }, "funding": { - "type": "patreon", + "type": "github", "url": "https://github.com/sponsors/rawify" } }, @@ -9411,17 +9424,6 @@ "node": ">= 0.4" } }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -9521,41 +9523,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-14.0.0.tgz", - "integrity": "sha512-X01vTgaX9SwaMq5DfImvS+3GMQFFs5HtrrlS9CuzUSzkxAf/tWGEyynuI+Qy7BjciMczZGjyVSmawYbP4eYhYA==", - "dependencies": { - "@sindresorhus/is": "^6.1.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.14", - "decompress-response": "^6.0.0", - "form-data-encoder": "^4.0.2", - "get-stream": "^8.0.1", - "http2-wrapper": "^2.2.1", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^4.0.1", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/got/node_modules/@sindresorhus/is": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.1.0.tgz", - "integrity": "sha512-BuvU07zq3tQ/2SIgBsEuxKYDyDjC0n7Zir52bpHy2xnBbW81+po43aLFPLbeV3HRAheFbGud1qgcqSYfhtHMAg==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -9924,15 +9891,15 @@ } }, "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" @@ -9942,16 +9909,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/hast-util-to-string": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz", @@ -10471,9 +10428,9 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/inline-style-parser": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, "node_modules/invariant": { @@ -10936,12 +10893,6 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -11195,18 +11146,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/marked": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.0.tgz", - "integrity": "sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -13534,9 +13473,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", - "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz", + "integrity": "sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==", "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", @@ -13735,15 +13674,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/not": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz", @@ -13972,14 +13902,6 @@ "opener": "bin/opener-bin.js" } }, - "node_modules/p-cancelable": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz", - "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==", - "engines": { - "node": ">=14.16" - } - }, "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -14096,6 +14018,73 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/package-json/node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/package-json/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json/node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/package-json/node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -14353,9 +14342,9 @@ } }, "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14597,9 +14586,9 @@ } }, "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14635,9 +14624,9 @@ } }, "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14763,9 +14752,9 @@ } }, "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14801,9 +14790,9 @@ } }, "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15187,9 +15176,9 @@ } }, "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15430,9 +15419,9 @@ } }, "node_modules/postcss-preset-env": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.4.0.tgz", - "integrity": "sha512-2kqpOthQ6JhxqQq1FSAAZGe9COQv75Aw8WbsOvQVNJ2nSevc9Yx/IKZGuZ7XJ+iOTtVon7LfO7ELRzg8AZ+sdw==", + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.6.1.tgz", + "integrity": "sha512-yrk74d9EvY+W7+lO9Aj1QmjWY9q5NsKjK2V9drkOPZB/X6KZ0B3igKsHUYakb7oYVhnioWypQX3xGuePf89f3g==", "funding": [ { "type": "github", @@ -15470,23 +15459,27 @@ "@csstools/postcss-media-minmax": "^2.0.9", "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", "@csstools/postcss-nested-calc": "^4.0.0", - "@csstools/postcss-normalize-display-values": "^4.0.0", + "@csstools/postcss-normalize-display-values": "^4.0.1", "@csstools/postcss-oklab-function": "^4.0.12", + "@csstools/postcss-position-area-property": "^1.0.0", "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/postcss-property-rule-prelude-list": "^1.0.0", "@csstools/postcss-random-function": "^2.0.1", "@csstools/postcss-relative-color-syntax": "^3.0.12", "@csstools/postcss-scope-pseudo-class": "^4.0.1", "@csstools/postcss-sign-functions": "^1.1.4", "@csstools/postcss-stepped-value-functions": "^4.0.9", + "@csstools/postcss-syntax-descriptor-syntax-production": "^1.0.1", + "@csstools/postcss-system-ui-font-family": "^1.0.0", "@csstools/postcss-text-decoration-shorthand": "^4.0.3", "@csstools/postcss-trigonometric-functions": "^4.0.9", "@csstools/postcss-unset-value": "^4.0.0", - "autoprefixer": "^10.4.21", - "browserslist": "^4.26.0", + "autoprefixer": "^10.4.23", + "browserslist": "^4.28.1", "css-blank-pseudo": "^7.0.1", "css-has-pseudo": "^7.0.3", "css-prefers-color-scheme": "^10.0.0", - "cssdb": "^8.4.2", + "cssdb": "^8.6.0", "postcss-attribute-case-insensitive": "^7.0.1", "postcss-clamp": "^4.1.0", "postcss-color-functional-notation": "^7.0.12", @@ -15546,9 +15539,9 @@ } }, "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15639,9 +15632,9 @@ } }, "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15798,9 +15791,10 @@ } }, "node_modules/prism-react-renderer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz", - "integrity": "sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.1.tgz", + "integrity": "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==", + "license": "MIT", "dependencies": { "@types/prismjs": "^1.26.0", "clsx": "^2.0.0" @@ -15892,6 +15886,15 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -15907,12 +15910,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -15970,15 +15973,15 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" @@ -15993,6 +15996,35 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -16028,15 +16060,16 @@ } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^18.3.1" } }, "node_modules/react-fast-compare": { @@ -16194,9 +16227,9 @@ } }, "node_modules/recma-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz", - "integrity": "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", "license": "MIT", "dependencies": { "acorn-jsx": "^5.0.0", @@ -16208,6 +16241,9 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/recma-parse": { @@ -16591,9 +16627,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", - "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", "license": "MIT", "dependencies": { "mdast-util-mdx": "^3.0.0", @@ -16777,12 +16813,12 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -16927,15 +16963,19 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "license": "ISC" + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } @@ -17546,12 +17586,12 @@ } }, "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/source-map-js": { @@ -17648,9 +17688,9 @@ } }, "node_modules/std-env": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "license": "MIT" }, "node_modules/streamx": { @@ -17801,21 +17841,21 @@ } }, "node_modules/style-to-js": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz", - "integrity": "sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { - "style-to-object": "1.0.8" + "style-to-object": "1.0.14" } }, "node_modules/style-to-object": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", - "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.2.4" + "inline-style-parser": "0.2.7" } }, "node_modules/stylehacks": { @@ -17897,19 +17937,6 @@ "node": ">= 10" } }, - "node_modules/swr": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz", - "integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3", - "use-sync-external-store": "^1.4.0" - }, - "peerDependencies": { - "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", @@ -18055,18 +18082,6 @@ "tslib": "^2" } }, - "node_modules/throttleit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", - "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -18285,10 +18300,11 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18406,9 +18422,9 @@ } }, "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -18458,9 +18474,9 @@ } }, "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -18473,9 +18489,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -18607,18 +18623,11 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -18716,15 +18725,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18805,9 +18805,9 @@ } }, "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -19453,9 +19453,9 @@ "license": "ISC" }, "node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", "license": "MIT", "engines": { "node": ">=12.20" @@ -19464,15 +19464,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/zod": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", - "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/site/package.json b/site/package.json index a1220d6527..f9bbc20968 100644 --- a/site/package.json +++ b/site/package.json @@ -2,10 +2,6 @@ "name": "retina", "version": "0.0.0", "private": true, - "overrides": { - "trim": ">0.0.3", - "got": ">11.8.5" - }, "scripts": { "docusaurus": "docusaurus", "start": "docusaurus start", @@ -18,26 +14,26 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.9.1", - "@docusaurus/plugin-ideal-image": "^3.9.1", - "@docusaurus/preset-classic": "^3.9.1", - "@mdx-js/react": "^3.0.0", - "@types/react": "^18.3.7", - "clsx": "^2.0.0", - "docusaurus-lunr-search": "^3.5.0", + "@docusaurus/core": "^3.9.2", + "@docusaurus/plugin-ideal-image": "^3.9.2", + "@docusaurus/preset-classic": "^3.9.2", + "@mdx-js/react": "^3.1.1", + "@types/react": "^18.3.28", + "clsx": "^2.1.1", + "docusaurus-lunr-search": "^3.6.0", "micromatch": "^4.0.8", - "prism-react-renderer": "^2.3.1", + "prism-react-renderer": "^2.4.1", "react": "^18.3.1", - "react-dom": "^18.2.0", + "react-dom": "^18.3.1", "sharp": "^0.33.5" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.8.0", - "@docusaurus/tsconfig": "^3.8.0", - "@docusaurus/types": "^3.8.0", + "@docusaurus/module-type-aliases": "^3.9.2", + "@docusaurus/tsconfig": "^3.9.2", + "@docusaurus/types": "^3.9.2", "css-loader": "^7.1.2", "style-loader": "^4.0.0", - "typescript": "^5.6.2" + "typescript": "^5.7.3" }, "browserslist": { "production": [ @@ -52,6 +48,6 @@ ] }, "engines": { - "node": ">=16.14" + "node": ">=18.0.0" } } diff --git a/site/site/package-lock.json b/site/site/package-lock.json deleted file mode 100644 index ec73fec8ab..0000000000 --- a/site/site/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "site", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/site/src/pages/index.module.css b/site/src/pages/index.module.css index 108e3134d3..4ba57dc4ca 100644 --- a/site/src/pages/index.module.css +++ b/site/src/pages/index.module.css @@ -2,80 +2,3 @@ * CSS files with the .module.css suffix will be treated as CSS modules * and scoped locally. */ - -.heroBanner { - padding: 4rem 0; - text-align: center; - position: relative; - overflow: hidden; -} - -@media screen and (max-width: 996px) { - .heroBanner { - padding: 2rem; - } -} - -@media only screen and (max-width: 600px) { - .columns { - display: flex; - align-items: center; - word-break: break-word; - padding: 4rem 1.5rem; - } - - .column2 { - flex-grow: 2; - font-size: 0.75rem; - } -} - -.buttons { - display: flex; - align-items: center; - justify-content: center; -} - -.columns { - display: flex; - align-items: center; - padding: 4rem 1.5rem; - word-break: break-word -} - -.column1 { - text-align: center; - flex: none; - width: 33.3333%; - font-weight: 600; - font-size: calc(1rem + 1.8vw); -} - -.column2 { - flex-grow: 2; - font-size: calc(1rem + 0.3vw); -} - -.paragraph1 { - margin: 0 0 20px -} - -.features { - margin: 0 2vw; - width: 50%; -} - -.columns2 { - display: flex; - align-items: center; - padding: 4rem 1.5rem; - word-break: break-word; - margin: 0 calc(0rem + 5vw); -} - -.featurelist { - font-size: calc(0rem + 2vw); - flex-grow: 1; - margin-left: calc(0rem + 3vw); - list-style-position: inside; -} From adc6406c8b09fbe06bc1613eda8ea6bdeba4d935 Mon Sep 17 00:00:00 2001 From: Matthew McKeen Date: Tue, 17 Feb 2026 12:03:59 -0800 Subject: [PATCH 215/448] feat: expire stale advanced metrics after not being updated for some time (#1921) # Description With advanced metrics, high-cardinality labels can cause the metrics export to bloat leading to unbounded memory and resource usage. This PR sets up an optional TTL for advanced metrics defined in the `MetricsConfiguration` CRD. By default, the TTL is infinite and cleanup is not tracked or done. When defined, on a period equal to the TTL metrics which have not been updated within the last TTL duration will be removed from the metrics export. For counters and gauges that look like counters, this will be treated by Prometheus similar to any other missing metric (for example from an application restart). As long as functions like `rate` or `increase` are used, calculations will remain accurate. This also includes a refactor of the base metrics object as an interface, allowing mocking in tests and a clean API contract with child objects that compose it. ## Related Issue https://github.com/microsoft/retina/issues/1692 ## Checklist - [X] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [X] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [X] I have correctly attributed the author(s) of the code. - [X] I have tested the changes locally. - [X] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Deployed, modified CRD to enable/disable and change the TTL. Metrics are re-initialized as expected. Made sure that CRD validation rejects invalid TTL values. Also, added comprehensive tests for the TTL-based cleanup logic. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Matthew McKeen --- .../v1alpha1/metricsconfiguration_types.go | 4 + .../validate_metricconfiguration.go | 18 +- .../validate_metricconfiguration_test.go | 199 ++++++++++++++++++ .../crds/retina.sh_metricsconfigurations.yaml | 10 + docs/03-Metrics/configuration.md | 3 +- docs/05-Concepts/CRDs/MetricsConfiguration.md | 2 + pkg/metrics/interfaces.go | 6 + pkg/metrics/metrics.go | 7 + pkg/metrics/mock_types.go | 77 +++++++ pkg/metrics/types.go | 3 + pkg/module/metrics/basemetricsobject.go | 167 ++++++++++++++- pkg/module/metrics/basemetricsobject_test.go | 104 +++++++++ pkg/module/metrics/dns.go | 72 ++++--- pkg/module/metrics/dns_test.go | 172 ++++++++------- pkg/module/metrics/drops.go | 61 ++++-- pkg/module/metrics/drops_test.go | 75 +++++-- pkg/module/metrics/forward.go | 67 +++--- pkg/module/metrics/forward_test.go | 65 ++++-- pkg/module/metrics/metrics_module.go | 20 +- .../metrics/metrics_module_linux_test.go | 8 +- pkg/module/metrics/mock_basemetricsobject.go | 162 ++++++++++++++ pkg/module/metrics/tcpflags.go | 58 +++-- pkg/module/metrics/tcpflags_test.go | 54 ++++- pkg/module/metrics/tcpretrans.go | 60 ++++-- pkg/utils/attr_utils.go | 1 + 25 files changed, 1233 insertions(+), 242 deletions(-) create mode 100644 pkg/module/metrics/basemetricsobject_test.go create mode 100644 pkg/module/metrics/mock_basemetricsobject.go diff --git a/crd/api/v1alpha1/metricsconfiguration_types.go b/crd/api/v1alpha1/metricsconfiguration_types.go index 18902c6fa6..0044493a4d 100644 --- a/crd/api/v1alpha1/metricsconfiguration_types.go +++ b/crd/api/v1alpha1/metricsconfiguration_types.go @@ -41,6 +41,10 @@ type MetricsContextOptions struct { // +optional // +listType=set AdditionalLabels []string `json:"additionalLabels,omitempty"` + // TTL represents the time-to-live of the metrics collected + // Metrics which have not been updated within the TTL will be removed from export + // +optional + TTL string `json:"ttl,omitempty"` } // MetricsNamespaces indicates the namespaces to include or exclude in metric collection diff --git a/crd/api/v1alpha1/validations/validate_metricconfiguration.go b/crd/api/v1alpha1/validations/validate_metricconfiguration.go index 0a7a456d40..4945b40726 100644 --- a/crd/api/v1alpha1/validations/validate_metricconfiguration.go +++ b/crd/api/v1alpha1/validations/validate_metricconfiguration.go @@ -6,12 +6,16 @@ Licensed under the MIT license. package validations import ( + "errors" "fmt" + "time" "github.com/microsoft/retina/crd/api/v1alpha1" "github.com/microsoft/retina/pkg/utils" ) +var ErrNegativeTTL = errors.New("TTL cannot be negative") + // MetricsConfiguration validates the metrics configuration func MetricsCRD(metricsConfig *v1alpha1.MetricsConfiguration) error { if metricsConfig == nil { @@ -40,6 +44,15 @@ func MetricsSpec(metricsSpec v1alpha1.MetricsSpec) error { if !utils.IsAdvancedMetric(contextOption.MetricName) { return fmt.Errorf("%s is not a valid metric", contextOption.MetricName) } + if contextOption.TTL != "" { + ttl, err := time.ParseDuration(contextOption.TTL) + if err != nil { + return fmt.Errorf("invalid TTL format for metric %s: %w", contextOption.MetricName, err) + } + if ttl < 0 { + return fmt.Errorf("%w for metric %s", ErrNegativeTTL, contextOption.MetricName) + } + } } err := MetricsNamespaces(metricsSpec.Namespaces) @@ -152,10 +165,13 @@ func MetricsContextOptionsCompare(old, new []v1alpha1.MetricsContextOptions) boo return false } - if !utils.CompareStringSlice(oldContextOption.AdditionalLabels, newContextOption.AdditionalLabels) { + if oldContextOption.TTL != newContextOption.TTL { return false } + if !utils.CompareStringSlice(oldContextOption.AdditionalLabels, newContextOption.AdditionalLabels) { + return false + } } return true diff --git a/crd/api/v1alpha1/validations/validate_metricconfiguration_test.go b/crd/api/v1alpha1/validations/validate_metricconfiguration_test.go index d5197facb0..93626f29a3 100644 --- a/crd/api/v1alpha1/validations/validate_metricconfiguration_test.go +++ b/crd/api/v1alpha1/validations/validate_metricconfiguration_test.go @@ -98,6 +98,86 @@ func TestMetricsConfiguration(t *testing.T) { }, wantErr: false, }, + { + name: "valid metrics crd with TTL", + obj: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + TTL: "24h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Exclude: []string{"kube-system"}, + }, + }, + }, + wantErr: false, + }, + { + name: "valid metrics crd with zero TTL", + obj: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + TTL: "0", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Exclude: []string{"kube-system"}, + }, + }, + }, + wantErr: false, + }, + { + name: "invalid metrics crd with TTL", + obj: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + TTL: "24", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Exclude: []string{"kube-system"}, + }, + }, + }, + wantErr: true, + }, + { + name: "invalid metrics crd with negative TTL", + obj: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + TTL: "-24h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Exclude: []string{"kube-system"}, + }, + }, + }, + wantErr: true, + }, { name: "invalid metrics crd with random metric name", obj: &v1alpha1.MetricsConfiguration{ @@ -348,6 +428,125 @@ func TestCompare(t *testing.T) { }, equal: true, }, + { + name: "valid test 6", + old: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + SourceLabels: []string{"ns", "ip", "port"}, + TTL: "24h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Include: []string{"default", "test"}, + Exclude: []string{"kube-system"}, + }, + }, + }, + new: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + SourceLabels: []string{"ip", "port", "ns"}, + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Include: []string{"default", "test"}, + Exclude: []string{"kube-system"}, + }, + }, + }, + equal: false, + }, + { + name: "valid test 7", + old: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + SourceLabels: []string{"ns", "ip", "port"}, + TTL: "24h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Include: []string{"default", "test"}, + Exclude: []string{"kube-system"}, + }, + }, + }, + new: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + SourceLabels: []string{"ip", "port", "ns"}, + TTL: "24h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Include: []string{"default", "test"}, + Exclude: []string{"kube-system"}, + }, + }, + }, + equal: true, + }, + { + name: "valid test 8", + old: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + SourceLabels: []string{"ns", "ip", "port"}, + TTL: "24h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Include: []string{"default", "test"}, + Exclude: []string{"kube-system"}, + }, + }, + }, + new: &v1alpha1.MetricsConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metricsconfig", + }, + Spec: v1alpha1.MetricsSpec{ + ContextOptions: []v1alpha1.MetricsContextOptions{ + { + MetricName: "drop_count", + SourceLabels: []string{"ip", "port", "ns"}, + TTL: "12h", + }, + }, + Namespaces: v1alpha1.MetricsNamespaces{ + Include: []string{"default", "test"}, + Exclude: []string{"kube-system"}, + }, + }, + }, + equal: false, + }, } for _, tt := range tests { diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml index feb3d8956a..123fe4c108 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml @@ -75,6 +75,11 @@ spec: type: string type: array x-kubernetes-list-type: set + ttl: + description: |- + TTL represents the time-to-live of the metrics collected + Metrics which have not been updated within the TTL will be removed from export + type: string required: - metricName type: object @@ -136,6 +141,11 @@ spec: type: string type: array x-kubernetes-list-type: set + ttl: + description: |- + TTL represents the time-to-live of the metrics collected + Metrics which have not been updated within the TTL will be removed from export + type: string required: - metricName type: object diff --git a/docs/03-Metrics/configuration.md b/docs/03-Metrics/configuration.md index 87cd3e80ba..3c7ee9421e 100644 --- a/docs/03-Metrics/configuration.md +++ b/docs/03-Metrics/configuration.md @@ -5,6 +5,7 @@ You can enable/disable metrics by including/omitting their Plugin from `enabledP Via [MetricsConfiguration CRD](../05-Concepts/CRDs/MetricsConfiguration.md), you can further customize the following for your enabled plugins: - Which metrics to include -- Which metadata to include for a metric. +- Which metadata to include for a metric +- Time-to-live for a metric **Note**: If you enable [Annotations](./annotations.md), you cannot use the `MetricsConfiguration` CRD to specify which Pods to observe. diff --git a/docs/05-Concepts/CRDs/MetricsConfiguration.md b/docs/05-Concepts/CRDs/MetricsConfiguration.md index 2b59205c59..91a341fafa 100644 --- a/docs/05-Concepts/CRDs/MetricsConfiguration.md +++ b/docs/05-Concepts/CRDs/MetricsConfiguration.md @@ -24,6 +24,7 @@ The `MetricsConfiguration` CRD is defined with the following specifications: - `destinationLabels`: Represents the destination context labels, such as IP, Pod, port, workload (deployment/replicaset/statefulset/daemonset). - `metricName`: Indicates the name of the metric. - `sourceLabels`: Represents the source context labels, such as IP, Pod, port. + - `ttl`: Represents the time-to-live for the metric. If there are no metric updates for a particular set of context labels for this duration the metric will be removed from export. The value of `ttl` must be a valid Golang `time.Duration` string and non-negative. A zero `ttl` (the default) means that metrics are never removed from export. - **spec.namespaces:** Specifies the namespaces to include or exclude in metric collection. It includes the following properties: - `exclude`: Specifies namespaces to be excluded from metric collection. @@ -51,6 +52,7 @@ spec: - port additionalLabels: - direction + ttl: 24h - metricName: forward_count sourceLabels: - ip diff --git a/pkg/metrics/interfaces.go b/pkg/metrics/interfaces.go index ddb9a07a5b..cb556e82ac 100644 --- a/pkg/metrics/interfaces.go +++ b/pkg/metrics/interfaces.go @@ -9,12 +9,18 @@ import ( //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=interfaces.go -destination=mock_types.go -package=metrics +type MetricVec interface { + DeleteLabelValues(lvs ...string) bool +} + type CounterVec interface { + MetricVec WithLabelValues(lvs ...string) prometheus.Counter GetMetricWithLabelValues(lvs ...string) (prometheus.Counter, error) } type GaugeVec interface { + MetricVec WithLabelValues(lvs ...string) prometheus.Gauge GetMetricWithLabelValues(lvs ...string) (prometheus.Gauge, error) } diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 9169a08d8d..c40c2c39da 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -194,6 +194,13 @@ func InitializeMetrics() { parsedPacketsCounterDescription, ) + MetricsExpiredCounter = exporter.CreatePrometheusCounterVecForControlPlaneMetric( + exporter.DefaultRegistry, + expiredMetricsCounterName, + expiredMetricsCounterDescription, + utils.Metric, + ) + isInitialized = true metricsLogger.Info("Metrics initialized") } diff --git a/pkg/metrics/mock_types.go b/pkg/metrics/mock_types.go index 5d80bb22da..4dbc97c1ab 100644 --- a/pkg/metrics/mock_types.go +++ b/pkg/metrics/mock_types.go @@ -17,6 +17,47 @@ import ( gomock "go.uber.org/mock/gomock" ) +// MockMetricVec is a mock of MetricVec interface. +type MockMetricVec struct { + ctrl *gomock.Controller + recorder *MockMetricVecMockRecorder +} + +// MockMetricVecMockRecorder is the mock recorder for MockMetricVec. +type MockMetricVecMockRecorder struct { + mock *MockMetricVec +} + +// NewMockMetricVec creates a new mock instance. +func NewMockMetricVec(ctrl *gomock.Controller) *MockMetricVec { + mock := &MockMetricVec{ctrl: ctrl} + mock.recorder = &MockMetricVecMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMetricVec) EXPECT() *MockMetricVecMockRecorder { + return m.recorder +} + +// DeleteLabelValues mocks base method. +func (m *MockMetricVec) DeleteLabelValues(lvs ...string) bool { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range lvs { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteLabelValues", varargs...) + ret0, _ := ret[0].(bool) + return ret0 +} + +// DeleteLabelValues indicates an expected call of DeleteLabelValues. +func (mr *MockMetricVecMockRecorder) DeleteLabelValues(lvs ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLabelValues", reflect.TypeOf((*MockMetricVec)(nil).DeleteLabelValues), lvs...) +} + // MockCounterVec is a mock of CounterVec interface. type MockCounterVec struct { ctrl *gomock.Controller @@ -40,6 +81,24 @@ func (m *MockCounterVec) EXPECT() *MockCounterVecMockRecorder { return m.recorder } +// DeleteLabelValues mocks base method. +func (m *MockCounterVec) DeleteLabelValues(lvs ...string) bool { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range lvs { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteLabelValues", varargs...) + ret0, _ := ret[0].(bool) + return ret0 +} + +// DeleteLabelValues indicates an expected call of DeleteLabelValues. +func (mr *MockCounterVecMockRecorder) DeleteLabelValues(lvs ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLabelValues", reflect.TypeOf((*MockCounterVec)(nil).DeleteLabelValues), lvs...) +} + // GetMetricWithLabelValues mocks base method. func (m *MockCounterVec) GetMetricWithLabelValues(lvs ...string) (prometheus.Counter, error) { m.ctrl.T.Helper() @@ -100,6 +159,24 @@ func (m *MockGaugeVec) EXPECT() *MockGaugeVecMockRecorder { return m.recorder } +// DeleteLabelValues mocks base method. +func (m *MockGaugeVec) DeleteLabelValues(lvs ...string) bool { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range lvs { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteLabelValues", varargs...) + ret0, _ := ret[0].(bool) + return ret0 +} + +// DeleteLabelValues indicates an expected call of DeleteLabelValues. +func (mr *MockGaugeVecMockRecorder) DeleteLabelValues(lvs ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLabelValues", reflect.TypeOf((*MockGaugeVec)(nil).DeleteLabelValues), lvs...) +} + // GetMetricWithLabelValues mocks base method. func (m *MockGaugeVec) GetMetricWithLabelValues(lvs ...string) (prometheus.Gauge, error) { m.ctrl.T.Helper() diff --git a/pkg/metrics/types.go b/pkg/metrics/types.go index 0803f62a71..cbc76f46ad 100644 --- a/pkg/metrics/types.go +++ b/pkg/metrics/types.go @@ -13,6 +13,7 @@ const ( pluginManagerFailedToReconcileCounterName = "plugin_manager_failed_to_reconcile" lostEventsCounterName = "lost_events_counter" parsedPacketsCounterName = "parsed_packets_counter" + expiredMetricsCounterName = "expired_metrics_counter" // Windows hnsStats = "windows_hns_stats" @@ -45,6 +46,7 @@ const ( pluginManagerFailedToReconcileCounterDescription = "Number of times the plugin manager failed to reconcile the plugins" lostEventsCounterDescription = "Number of events lost in control plane" parsedPacketsCounterDescription = "Number of packets parsed by the packetparser plugin" + expiredMetricsCounterDescription = "Number of metrics expired due to lack of updates and no longer exported" // Conntrack metrics ConntrackPacketTxDescription = "Number of tx packets" @@ -93,6 +95,7 @@ var ( PluginManagerFailedToReconcileCounter CounterVec LostEventsCounter CounterVec ParsedPacketsCounter CounterVec + MetricsExpiredCounter CounterVec // DNS Metrics. DNSRequestCounter CounterVec diff --git a/pkg/module/metrics/basemetricsobject.go b/pkg/module/metrics/basemetricsobject.go index 19f0b9e675..0b4bb7b286 100644 --- a/pkg/module/metrics/basemetricsobject.go +++ b/pkg/module/metrics/basemetricsobject.go @@ -3,29 +3,186 @@ package metrics import ( + "context" + "strings" + "sync" + "time" + api "github.com/microsoft/retina/crd/api/v1alpha1" "github.com/microsoft/retina/pkg/log" + "go.uber.org/zap" ) +type expireFn func(lbs []string) bool + +type updated struct { + t time.Time + lbs []string +} + +//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=basemetricsobject.go -destination=mock_basemetricsobject.go -package=metrics +type baseMetricInterface interface { + // This func is used to clean up any resources used by the base metric object + clean() + isAdvanced() bool + sourceCtx() ContextOptionsInterface + destinationCtx() ContextOptionsInterface + additionalLabels() []string + isLocalContext() bool + // This func is used to track updates to the metric labels. It is called by the child metric object whenever the metric is updated + updated(lbs []string) + getLogger() *log.ZapLogger + // Returns the full set of tracked metric labels, this is expensive so should only be used for testing and debugging purposes + trackedMetricLabels() [][]string +} + type baseMetricObject struct { + *sync.RWMutex advEnable bool contextMode enrichmentContext ctxOptions *api.MetricsContextOptions srcCtx ContextOptionsInterface dstCtx ContextOptionsInterface l *log.ZapLogger + lastUpdated map[string]updated + expireFn expireFn + cancelFn context.CancelFunc + ctx context.Context +} + +func (b *baseMetricObject) additionalLabels() []string { + if b.ctxOptions == nil { + return nil + } + + return b.ctxOptions.AdditionalLabels +} + +func (b *baseMetricObject) trackedMetricLabels() [][]string { + if b.expireFn == nil { + return nil + } + + b.RLock() + defer b.RUnlock() + + labels := make([][]string, 0, len(b.lastUpdated)) + for _, u := range b.lastUpdated { + labels = append(labels, u.lbs) + } + + return labels +} + +func (b *baseMetricObject) isAdvanced() bool { + return b.advEnable +} + +func (b *baseMetricObject) sourceCtx() ContextOptionsInterface { + return b.srcCtx +} + +func (b *baseMetricObject) destinationCtx() ContextOptionsInterface { + return b.dstCtx +} + +func (b *baseMetricObject) getLogger() *log.ZapLogger { + return b.l } -func newBaseMetricsObject(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext) baseMetricObject { +func (b *baseMetricObject) expire(ttl time.Duration) int { + if b.expireFn == nil { + return 0 + } + + b.Lock() + defer b.Unlock() + + var expired int + n := make(map[string]updated) + + for k, u := range b.lastUpdated { + if time.Since(u.t) >= ttl { + d := b.expireFn(u.lbs) + if d { + expired++ + } + } else { + n[k] = u + } + } + + b.lastUpdated = n + + return expired +} + +func (b *baseMetricObject) updated(lbs []string) { + // no expiration function is defined, so we don't need to track updates + if b.expireFn == nil { + return + } + + k := strings.Join(lbs, "") + + b.Lock() + defer b.Unlock() + + b.lastUpdated[k] = updated{ + t: time.Now(), + lbs: lbs, + } +} + +func newBaseMetricsObject(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext, expire expireFn, ttl time.Duration) *baseMetricObject { + expireOrInfiniteTTL := expire + if ttl <= 0 { + // infinite TTL, so make sure the expiration function is unset + expireOrInfiniteTTL = nil + } + b := baseMetricObject{ advEnable: ctxOptions.IsAdvanced(), ctxOptions: ctxOptions, l: fl, contextMode: isLocalContext, + expireFn: expireOrInfiniteTTL, + } + + if expireOrInfiniteTTL != nil { + // only initialize these if we have a valid expiration function to save some memory + b.RWMutex = &sync.RWMutex{} + b.lastUpdated = make(map[string]updated) + ctx, cancel := context.WithCancel(context.Background()) + b.ctx = ctx + b.cancelFn = cancel + b.l.Info( + "Starting metric expiration routine: "+ctxOptions.MetricName, + zap.Duration("ttl", ttl), + ) + go func() { + ticker := time.NewTicker(ttl) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + b.l.Info("Stopping metric expiration routine: " + b.ctxOptions.MetricName) + return + case t := <-ticker.C: + b.l.Debug("Expiring metrics: " + b.ctxOptions.MetricName) + n := b.expire(ttl) + b.l.Debug( + "Metric expiration finished: "+b.ctxOptions.MetricName, + zap.Time("next_expiration", t.Add(ttl)), + zap.Int("expired", n), + ) + } + } + }() } b.populateCtxOptions(ctxOptions) - return b + return &b } func (b *baseMetricObject) populateCtxOptions(ctxOptions *api.MetricsContextOptions) { @@ -51,3 +208,9 @@ func (b *baseMetricObject) populateCtxOptions(ctxOptions *api.MetricsContextOpti func (b *baseMetricObject) isLocalContext() bool { return b.contextMode == localContext } + +func (b *baseMetricObject) clean() { + if b.cancelFn != nil { + b.cancelFn() + } +} diff --git a/pkg/module/metrics/basemetricsobject_test.go b/pkg/module/metrics/basemetricsobject_test.go new file mode 100644 index 0000000000..6a33cd39b1 --- /dev/null +++ b/pkg/module/metrics/basemetricsobject_test.go @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +package metrics + +import ( + "runtime" + "slices" + "testing" + "time" + + api "github.com/microsoft/retina/crd/api/v1alpha1" + "github.com/microsoft/retina/pkg/log" +) + +func TestBaseMetricObject(t *testing.T) { + l, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + if err != nil { + t.Fatalf("failed to set up logger: %v", err) + } + + tests := []struct { + name string + ttl time.Duration + trackMetrics bool + }{ + { + name: "test base metric object zero ttl", + ttl: 0, + trackMetrics: false, + }, + { + name: "test base metric object negative ttl", + ttl: -time.Millisecond, + trackMetrics: false, + }, + { + name: "test base metric object positive ttl", + ttl: time.Millisecond, + trackMetrics: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + before := runtime.NumGoroutine() + expireCalled := new([]string) + b := newBaseMetricsObject( + &api.MetricsContextOptions{ + MetricName: "test_metric", + }, + l, + localContext, + func(lbs []string) bool { + *expireCalled = lbs + return true + }, + tt.ttl, + ) + + testLabels := []string{"test"} + b.updated(testLabels) + + metrics := len(b.trackedMetricLabels()) + if tt.trackMetrics { + if metrics != 1 { + t.Errorf("expected 1 tracked metric label, got %d", metrics) + } + } else { + if metrics != 0 { + t.Errorf("expected 0 tracked metric labels, got %d", metrics) + } + } + + // If we have a positive TTL, we should see the expire function get called after the TTL has passed + if tt.ttl > 0 { + time.Sleep(tt.ttl + time.Millisecond*100) + if !slices.Equal(*expireCalled, testLabels) { + t.Errorf("expected expire to be called with %v, got %v", testLabels, *expireCalled) + } + metrics = len(b.trackedMetricLabels()) + if metrics != 0 { + t.Errorf("expected 0 tracked metric labels after expiration, got %d", metrics) + } + } else if len(*expireCalled) != 0 { + t.Errorf("expected expire to not be called, but got %v", *expireCalled) + } + + b.clean() + if b.expireFn != nil { + <-b.ctx.Done() + } + + // Wait for any goroutines to exit after clean is called + if tt.trackMetrics { + time.Sleep(tt.ttl + time.Millisecond*100) + } + + after := runtime.NumGoroutine() + if after != before { + t.Errorf("expected number of goroutines to be the same as before, expected %d, got %d", before, after) + } + }) + } +} diff --git a/pkg/module/metrics/dns.go b/pkg/module/metrics/dns.go index eaf7eb4428..96f4886951 100644 --- a/pkg/module/metrics/dns.go +++ b/pkg/module/metrics/dns.go @@ -7,6 +7,7 @@ import ( "fmt" "strconv" "strings" + "time" v1 "github.com/cilium/cilium/api/v1/flow" api "github.com/microsoft/retina/crd/api/v1alpha1" @@ -30,21 +31,21 @@ var ( ) type DNSMetrics struct { - baseMetricObject + baseMetricInterface dnsMetrics metricsinit.CounterVec metricName string } -func NewDNSMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext) *DNSMetrics { +func NewDNSMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext, ttl time.Duration) *DNSMetrics { if ctxOptions == nil || !strings.Contains(strings.ToLower(ctxOptions.MetricName), "dns") { return nil } fl = fl.Named("dns-metricsmodule") fl.Info("Creating DNS count metrics", zap.Any("options", ctxOptions)) - return &DNSMetrics{ - baseMetricObject: newBaseMetricsObject(ctxOptions, fl, isLocalContext), - } + d := &DNSMetrics{} + d.baseMetricInterface = newBaseMetricsObject(ctxOptions, fl, isLocalContext, d.expire, ttl) + return d } func (d *DNSMetrics) Init(metricName string) { @@ -71,14 +72,14 @@ func (d *DNSMetrics) Init(metricName string) { func (d *DNSMetrics) getRequestLabels() []string { labels := utils.DNSRequestLabels - if d.srcCtx != nil { - labels = append(labels, d.srcCtx.getLabels()...) - d.l.Info("src labels", zap.Any("labels", labels)) + if d.sourceCtx() != nil { + labels = append(labels, d.sourceCtx().getLabels()...) + d.getLogger().Info("src labels", zap.Any("labels", labels)) } - if d.dstCtx != nil { - labels = append(labels, d.dstCtx.getLabels()...) - d.l.Info("dst labels", zap.Any("labels", labels)) + if d.destinationCtx() != nil { + labels = append(labels, d.destinationCtx().getLabels()...) + d.getLogger().Info("dst labels", zap.Any("labels", labels)) } return labels @@ -86,14 +87,14 @@ func (d *DNSMetrics) getRequestLabels() []string { func (d *DNSMetrics) getResponseLabels() []string { labels := utils.DNSResponseLabels - if d.srcCtx != nil { - labels = append(labels, d.srcCtx.getLabels()...) - d.l.Info("src labels", zap.Any("labels", labels)) + if d.sourceCtx() != nil { + labels = append(labels, d.sourceCtx().getLabels()...) + d.getLogger().Info("src labels", zap.Any("labels", labels)) } - if d.dstCtx != nil { - labels = append(labels, d.dstCtx.getLabels()...) - d.l.Info("dst labels", zap.Any("labels", labels)) + if d.destinationCtx() != nil { + labels = append(labels, d.destinationCtx().getLabels()...) + d.getLogger().Info("dst labels", zap.Any("labels", labels)) } return labels @@ -172,7 +173,7 @@ func (d *DNSMetrics) ProcessFlow(flow *v1.Flow) { labels, err := d.getLabelsForProcessFlow(flow) if err != nil { - d.l.Error("Failed to get labels for process flow", zap.Error(err)) + d.getLogger().Error("Failed to get labels for process flow", zap.Error(err)) return } @@ -180,33 +181,33 @@ func (d *DNSMetrics) ProcessFlow(flow *v1.Flow) { return } - if d.srcCtx != nil { - srcLabels := d.srcCtx.getValues(flow) + if d.sourceCtx() != nil { + srcLabels := d.sourceCtx().getValues(flow) if len(srcLabels) > 0 { labels = append(labels, srcLabels...) } } - if d.dstCtx != nil { - dstLabels := d.dstCtx.getValues(flow) + if d.destinationCtx() != nil { + dstLabels := d.destinationCtx().getValues(flow) if len(dstLabels) > 0 { labels = append(labels, dstLabels...) } } - d.dnsMetrics.WithLabelValues(labels...).Inc() - d.l.Debug("Update dns metric in remote ctx", zap.Any("metric", d.dnsMetrics), zap.Any("labels", labels)) + d.update(labels) + d.getLogger().Debug("Update dns metric in remote ctx", zap.Any("metric", d.dnsMetrics), zap.Any("labels", labels)) } func (d *DNSMetrics) processLocalCtxFlow(flow *v1.Flow) { - labelValuesMap := d.srcCtx.getLocalCtxValues(flow) + labelValuesMap := d.sourceCtx().getLocalCtxValues(flow) if labelValuesMap == nil { return } labels, err := d.getLabelsForProcessFlow(flow) if err != nil { - d.l.Error("Failed to get labels for process flow", zap.Error(err)) + d.getLogger().Error("Failed to get labels for process flow", zap.Error(err)) return } @@ -230,10 +231,27 @@ func (d *DNSMetrics) processLocalCtxFlow(flow *v1.Flow) { } else { return } + d.update(labels) + d.getLogger().Debug("Update dns metric in local ctx", zap.Any("metric", d.dnsMetrics), zap.Any("labels", labels)) +} + +func (d *DNSMetrics) expire(labels []string) bool { + var del bool + if d.dnsMetrics != nil { + del = d.dnsMetrics.DeleteLabelValues(labels...) + if del { + metricsinit.MetricsExpiredCounter.WithLabelValues(d.metricName).Inc() + } + } + return del +} + +func (d *DNSMetrics) update(labels []string) { d.dnsMetrics.WithLabelValues(labels...).Inc() - d.l.Debug("Update dns metric in local ctx", zap.Any("metric", d.dnsMetrics), zap.Any("labels", labels)) + d.updated(labels) } func (d *DNSMetrics) Clean() { exporter.UnregisterMetric(exporter.AdvancedRegistry, metricsinit.ToPrometheusType(d.dnsMetrics)) + d.clean() } diff --git a/pkg/module/metrics/dns_test.go b/pkg/module/metrics/dns_test.go index 55dd833950..4ada8ff21d 100644 --- a/pkg/module/metrics/dns_test.go +++ b/pkg/module/metrics/dns_test.go @@ -6,10 +6,12 @@ package metrics import ( "reflect" "testing" + "time" "github.com/cilium/cilium/api/v1/flow" + "github.com/microsoft/retina/crd/api/v1alpha1" "github.com/microsoft/retina/pkg/log" - "github.com/microsoft/retina/pkg/metrics" + metricsinit "github.com/microsoft/retina/pkg/metrics" "github.com/microsoft/retina/pkg/utils" "github.com/prometheus/client_golang/prometheus" "go.uber.org/mock/gomock" @@ -35,7 +37,7 @@ func TestGetLabels(t *testing.T) { name: "basic context request labels", want: utils.DNSRequestLabels, d: &DNSMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ srcCtx: nil, dstCtx: nil, }, @@ -46,7 +48,7 @@ func TestGetLabels(t *testing.T) { name: "basic context response labels", want: utils.DNSResponseLabels, d: &DNSMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ srcCtx: nil, dstCtx: nil, }, @@ -57,7 +59,7 @@ func TestGetLabels(t *testing.T) { name: "local context request labels", want: append(utils.DNSRequestLabels, "ip", "namespace", "podname", "workload_kind", "workload_name", "service", "port"), d: &DNSMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ srcCtx: &ContextOptions{ option: localCtx, IP: true, @@ -202,114 +204,134 @@ func TestProcessLocalCtx(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - testR := &flow.Flow{} - extR := utils.NewExtensions() - utils.AddDNSInfo(testR, extR, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.SetExtensions(testR, extR) - - testIngress := &flow.Flow{TrafficDirection: flow.TrafficDirection_INGRESS} - extIngress := utils.NewExtensions() - utils.AddDNSInfo(testIngress, extIngress, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.SetExtensions(testIngress, extIngress) - - testEgress := &flow.Flow{TrafficDirection: flow.TrafficDirection_EGRESS} - extEgress := utils.NewExtensions() - utils.AddDNSInfo(testEgress, extEgress, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) - utils.SetExtensions(testEgress, extEgress) - tests := []struct { name string - d *DNSMetrics input *flow.Flow - output map[string][]string expectedLabels []string metricsUpdate bool }{ { - name: "No context labels", - input: nil, - output: nil, - d: &DNSMetrics{}, + name: "No context labels", + input: &flow.Flow{ + Verdict: utils.Verdict_DNS, + }, metricsUpdate: false, }, { - name: "Only ingress labels", - input: testR, - output: map[string][]string{ - ingress: {"PodA", "NamespaceA"}, - egress: nil, - }, - d: &DNSMetrics{ - metricName: utils.DNSResponseCounterName, - baseMetricObject: baseMetricObject{ - l: l, + name: "Only ingress labels", + input: &flow.Flow{ + Verdict: utils.Verdict_DNS, + TrafficDirection: flow.TrafficDirection_INGRESS, + Destination: &flow.Endpoint{ + PodName: "PodB", + Namespace: "NamespaceB", }, }, - expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "PodA", "NamespaceA"}, + expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "NamespaceB", "PodB"}, metricsUpdate: true, }, { - name: "Only egress labels", - input: testR, - output: map[string][]string{ - ingress: nil, - egress: {"PodA", "NamespaceA"}, - }, - d: &DNSMetrics{ - metricName: utils.DNSResponseCounterName, - baseMetricObject: baseMetricObject{ - l: l, + name: "Only egress labels", + input: &flow.Flow{ + Verdict: utils.Verdict_DNS, + TrafficDirection: flow.TrafficDirection_EGRESS, + Source: &flow.Endpoint{ + PodName: "PodA", + Namespace: "NamespaceA", }, }, - expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "PodA", "NamespaceA"}, + expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "NamespaceA", "PodA"}, metricsUpdate: true, }, { - name: "Both ingress and egress labels with ingress flow", - input: testIngress, - output: map[string][]string{ - ingress: {"PodA", "NamespaceA"}, - egress: {"PodB", "NamespaceB"}, - }, - d: &DNSMetrics{ - metricName: utils.DNSResponseCounterName, - baseMetricObject: baseMetricObject{ - l: l, + name: "Both ingress and egress labels with ingress flow", + input: &flow.Flow{ + Verdict: utils.Verdict_DNS, + TrafficDirection: flow.TrafficDirection_INGRESS, + Destination: &flow.Endpoint{ + PodName: "PodA", + Namespace: "NamespaceA", + }, + Source: &flow.Endpoint{ + PodName: "PodB", + Namespace: "NamespaceB", }, }, - expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "PodA", "NamespaceA"}, + expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "NamespaceA", "PodA"}, metricsUpdate: true, }, { - name: "Both ingress and egress labels with egress flow", - input: testEgress, - output: map[string][]string{ - ingress: {"PodA", "NamespaceA"}, - egress: {"PodB", "NamespaceB"}, - }, - d: &DNSMetrics{ - metricName: utils.DNSResponseCounterName, - baseMetricObject: baseMetricObject{ - l: l, + name: "Both source and destination labels with egress flow", + input: &flow.Flow{ + Verdict: utils.Verdict_DNS, + TrafficDirection: flow.TrafficDirection_EGRESS, + Source: &flow.Endpoint{ + PodName: "PodB", + Namespace: "NamespaceB", + }, + Destination: &flow.Endpoint{ + PodName: "PodA", + Namespace: "NamespaceA", }, }, - expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "PodB", "NamespaceB"}, + expectedLabels: []string{"NOERROR", "A", "bing.com", "1.1.1.1", "1", "NamespaceB", "PodB"}, metricsUpdate: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - m := NewMockContextOptionsInterface(ctrl) //nolint:typecheck - m.EXPECT().getLocalCtxValues(tt.input).Return(tt.output).Times(1) + ext := utils.NewExtensions() + utils.AddDNSInfo(tt.input, ext, "R", 0, "bing.com", []string{"A"}, 1, []string{"1.1.1.1"}) + utils.SetExtensions(tt.input, ext) - mockCV := metrics.NewMockCounterVec(ctrl) + mockCV := metricsinit.NewMockCounterVec(ctrl) if tt.metricsUpdate { mockCV.EXPECT().WithLabelValues(tt.expectedLabels).Return(c).Times(1) } - tt.d.dnsMetrics = mockCV - tt.d.srcCtx = m - tt.d.processLocalCtxFlow(tt.input) + ctxOptions := &v1alpha1.MetricsContextOptions{ + MetricName: utils.DNSResponseCounterName, + SourceLabels: []string{ + podCtxOption, + namespaceCtxOption, + }, + } + d := NewDNSMetrics(ctxOptions, l, localContext, 0) + d.dnsMetrics = mockCV + + d.ProcessFlow(tt.input) + + // There should be no tracked metrics when TTL is infinite + assert.Equal(t, 0, len(d.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite") + + // Test TTL based expiration + metricsinit.InitializeMetrics() + + // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics + d = NewDNSMetrics(ctxOptions, l, localContext, time.Minute) + d.dnsMetrics = mockCV + + if tt.metricsUpdate { + mockCV.EXPECT().WithLabelValues(tt.expectedLabels).Return(c).Times(1) + } + + d.ProcessFlow(tt.input) + + if tt.metricsUpdate { + mockCV.EXPECT().DeleteLabelValues(tt.expectedLabels).Return(true).Times(1) + } + + for _, ls := range d.trackedMetricLabels() { + assert.Check(t, d.expire(ls), "metrics should expire successfully") + } + + // Test that clean calls the base object + baseMetricObjectMock := NewMockbaseMetricInterface(ctrl) + d.baseMetricInterface = baseMetricObjectMock + + baseMetricObjectMock.EXPECT().clean().Times(1) + + d.Clean() }) } } diff --git a/pkg/module/metrics/drops.go b/pkg/module/metrics/drops.go index cf5db7d7a1..f1ed9bc345 100644 --- a/pkg/module/metrics/drops.go +++ b/pkg/module/metrics/drops.go @@ -5,6 +5,7 @@ package metrics import ( "strings" + "time" v1 "github.com/cilium/cilium/api/v1/flow" api "github.com/microsoft/retina/crd/api/v1alpha1" @@ -24,21 +25,21 @@ const ( ) type DropCountMetrics struct { - baseMetricObject + baseMetricInterface dropMetric metrics.GaugeVec metricName string } -func NewDropCountMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext) *DropCountMetrics { +func NewDropCountMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext, ttl time.Duration) *DropCountMetrics { if ctxOptions == nil || !strings.Contains(strings.ToLower(ctxOptions.MetricName), "drop") { return nil } fl = fl.Named("dropreason-metricsmodule") fl.Info("Creating drop count metrics", zap.Any("options", ctxOptions)) - return &DropCountMetrics{ - baseMetricObject: newBaseMetricsObject(ctxOptions, fl, isLocalContext), - } + d := &DropCountMetrics{} + d.baseMetricInterface = newBaseMetricsObject(ctxOptions, fl, isLocalContext, d.expire, ttl) + return d } func (d *DropCountMetrics) Init(metricName string) { @@ -56,7 +57,7 @@ func (d *DropCountMetrics) Init(metricName string) { TotalDropBytesDesc, d.getLabels()...) default: - d.l.Error("unknown metric name", zap.String("metricName", metricName)) + d.getLogger().Error("unknown metric name", zap.String("metricName", metricName)) } d.metricName = metricName } @@ -67,14 +68,14 @@ func (d *DropCountMetrics) getLabels() []string { utils.Direction, } - if d.srcCtx != nil { - labels = append(labels, d.srcCtx.getLabels()...) - d.l.Info("src labels", zap.Any("labels", labels)) + if d.sourceCtx() != nil { + labels = append(labels, d.sourceCtx().getLabels()...) + d.getLogger().Info("src labels", zap.Any("labels", labels)) } - if d.dstCtx != nil { - labels = append(labels, d.dstCtx.getLabels()...) - d.l.Info("dst labels", zap.Any("labels", labels)) + if d.destinationCtx() != nil { + labels = append(labels, d.destinationCtx().getLabels()...) + d.getLogger().Info("dst labels", zap.Any("labels", labels)) } // No additional context options @@ -84,6 +85,7 @@ func (d *DropCountMetrics) getLabels() []string { func (d *DropCountMetrics) Clean() { exporter.UnregisterMetric(exporter.AdvancedRegistry, metrics.ToPrometheusType(d.dropMetric)) + d.clean() } // TODO: update ProcessFlow with bytes metrics. We are only accounting for count. @@ -111,20 +113,20 @@ func (d *DropCountMetrics) ProcessFlow(flow *v1.Flow) { flow.TrafficDirection.String(), } - if !d.advEnable { + if !d.isAdvanced() { d.update(flow, labels) return } - if d.srcCtx != nil { - srcLabels := d.srcCtx.getValues(flow) + if d.sourceCtx() != nil { + srcLabels := d.sourceCtx().getValues(flow) if len(srcLabels) > 0 { labels = append(labels, srcLabels...) } } - if d.dstCtx != nil { - dstLabel := d.dstCtx.getValues(flow) + if d.destinationCtx() != nil { + dstLabel := d.destinationCtx().getValues(flow) if len(dstLabel) > 0 { labels = append(labels, dstLabel...) } @@ -133,11 +135,11 @@ func (d *DropCountMetrics) ProcessFlow(flow *v1.Flow) { // No additional context options d.update(flow, labels) - d.l.Debug("drop count metric is added", zap.Any("labels", labels)) + d.getLogger().Debug("drop count metric is added", zap.Any("labels", labels)) } func (d *DropCountMetrics) processLocalCtxFlow(flow *v1.Flow) { - labelValuesMap := d.srcCtx.getLocalCtxValues(flow) + labelValuesMap := d.sourceCtx().getLocalCtxValues(flow) if labelValuesMap == nil { return } @@ -149,7 +151,7 @@ func (d *DropCountMetrics) processLocalCtxFlow(flow *v1.Flow) { labels = append(labels, dropReason, ingress) labels = append(labels, labelValuesMap[ingress]...) d.update(flow, labels) - d.l.Debug("drop count metric is added in INGRESS in local ctx", zap.Any("labels", labels)) + d.getLogger().Debug("drop count metric is added in INGRESS in local ctx", zap.Any("labels", labels)) } if l := len(labelValuesMap[egress]); l > 0 { @@ -157,15 +159,32 @@ func (d *DropCountMetrics) processLocalCtxFlow(flow *v1.Flow) { labels = append(labels, dropReason, egress) labels = append(labels, labelValuesMap[egress]...) d.update(flow, labels) - d.l.Debug("drop count metric is added in EGRESS in local ctx", zap.Any("labels", labels)) + d.getLogger().Debug("drop count metric is added in EGRESS in local ctx", zap.Any("labels", labels)) + } +} + +func (d *DropCountMetrics) expire(labels []string) bool { + var del bool + if d.dropMetric != nil { + del = d.dropMetric.DeleteLabelValues(labels...) + if del { + metrics.MetricsExpiredCounter.WithLabelValues(d.metricName).Inc() + } } + return del } func (d *DropCountMetrics) update(fl *v1.Flow, labels []string) { + var updated bool switch d.metricName { case utils.DroppedPacketsGaugeName: + updated = true d.dropMetric.WithLabelValues(labels...).Inc() case utils.DropBytesGaugeName: + updated = true d.dropMetric.WithLabelValues(labels...).Add(float64(utils.PacketSize(fl))) } + if updated { + d.updated(labels) + } } diff --git a/pkg/module/metrics/drops_test.go b/pkg/module/metrics/drops_test.go index bc2e9f707f..2f8650af5d 100644 --- a/pkg/module/metrics/drops_test.go +++ b/pkg/module/metrics/drops_test.go @@ -6,6 +6,7 @@ package metrics import ( "testing" + "time" "github.com/cilium/cilium/api/v1/flow" "github.com/microsoft/retina/crd/api/v1alpha1" @@ -64,6 +65,7 @@ func TestNewDrop(t *testing.T) { }, exepectedLabels: []string{"reason", "direction"}, metricCall: 1, + trackedMetrics: 1, }, { name: "plain opts dropped verdict nil flow", @@ -87,8 +89,9 @@ func TestNewDrop(t *testing.T) { "reason", "direction", }, - metricCall: 1, - nilObj: true, + metricCall: 1, + trackedMetrics: 1, + nilObj: true, }, { name: "source opts 1", @@ -111,7 +114,8 @@ func TestNewDrop(t *testing.T) { "source_service", "source_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "dest opts 1", @@ -134,7 +138,8 @@ func TestNewDrop(t *testing.T) { "destination_service", "destination_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "source opts with flow", @@ -158,7 +163,8 @@ func TestNewDrop(t *testing.T) { "source_service", "source_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "forward source opts with flow", @@ -182,8 +188,9 @@ func TestNewDrop(t *testing.T) { "source_service", "source_port", }, - metricCall: 1, - nilObj: true, + metricCall: 1, + trackedMetrics: 1, + nilObj: true, }, { name: "drop source opts with flow in localcontext", @@ -207,9 +214,10 @@ func TestNewDrop(t *testing.T) { "service", "port", }, - metricCall: 1, - nilObj: false, - localContext: localContext, + metricCall: 1, + trackedMetrics: 1, + nilObj: false, + localContext: localContext, }, { name: "drop source opts with destination flow in localcontext", @@ -233,9 +241,10 @@ func TestNewDrop(t *testing.T) { "service", "port", }, - metricCall: 1, - nilObj: false, - localContext: localContext, + metricCall: 1, + trackedMetrics: 1, + nilObj: false, + localContext: localContext, }, { name: "drop source opts with source and destination flow in localcontext", @@ -260,9 +269,10 @@ func TestNewDrop(t *testing.T) { "service", "port", }, - metricCall: 2, - nilObj: false, - localContext: localContext, + metricCall: 2, + trackedMetrics: 2, + nilObj: false, + localContext: localContext, }, } @@ -270,7 +280,7 @@ func TestNewDrop(t *testing.T) { for _, metricName := range []string{"drop_count", "drop_bytes"} { log.Logger().Info("Running test name", zap.String("name", tc.name), zap.String("metricName", metricName)) ctrl := gomock.NewController(t) - f := NewDropCountMetrics(tc.opts, log.Logger(), tc.localContext) + f := NewDropCountMetrics(tc.opts, log.Logger(), tc.localContext, time.Duration(0)) if tc.nilObj { assert.Nil(t, f, "drop metrics should be nil Test Name: %s", tc.name) continue @@ -288,11 +298,40 @@ func TestNewDrop(t *testing.T) { dropMock.EXPECT().WithLabelValues(gomock.Any()).Return(testmetric).Times(tc.metricCall) - assert.Equal(t, f.advEnable, tc.checkIsAdvance, "advance metrics options should be equal Test Name: %s", tc.name) + assert.Equal(t, f.isAdvanced(), tc.checkIsAdvance, "advance metrics options should be equal Test Name: %s", tc.name) assert.Equal(t, tc.exepectedLabels, f.getLabels(), "labels should be equal Test Name: %s", tc.name) f.metricName = metricName f.ProcessFlow(tc.f) + + // There should be no tracked metrics when TTL is infinite + assert.Equal(t, 0, len(f.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite Test Name: %s", tc.name) + + // Test TTL based expiration + metricsinit.InitializeMetrics() + + // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics + f = NewDropCountMetrics(tc.opts, log.Logger(), tc.localContext, time.Minute) + f.dropMetric = dropMock + + dropMock.EXPECT().WithLabelValues(gomock.Any()).Return(testmetric).Times(tc.metricCall) + + f.metricName = metricName + f.ProcessFlow(tc.f) + + dropMock.EXPECT().DeleteLabelValues(gomock.Any()).Return(true).Times(tc.trackedMetrics) + + for _, ls := range f.trackedMetricLabels() { + assert.True(t, f.expire(ls), "metric should expire successfully Test Name: %s", tc.name) + } + + // Test that clean calls the base object + baseMetricObjectMock := NewMockbaseMetricInterface(ctrl) + f.baseMetricInterface = baseMetricObjectMock + + baseMetricObjectMock.EXPECT().clean().Times(1) + + f.Clean() ctrl.Finish() } } diff --git a/pkg/module/metrics/forward.go b/pkg/module/metrics/forward.go index 9ed694b2f3..e52e621779 100644 --- a/pkg/module/metrics/forward.go +++ b/pkg/module/metrics/forward.go @@ -7,6 +7,7 @@ import ( "slices" "strconv" "strings" + "time" v1 "github.com/cilium/cilium/api/v1/flow" api "github.com/microsoft/retina/crd/api/v1alpha1" @@ -28,22 +29,22 @@ const ( ) type ForwardMetrics struct { - baseMetricObject + baseMetricInterface forwardMetric metricsinit.GaugeVec // bytesMetric metricsinit.IGaugeVec metricName string } -func NewForwardCountMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext) *ForwardMetrics { +func NewForwardCountMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext, ttl time.Duration) *ForwardMetrics { if ctxOptions == nil || !strings.Contains(strings.ToLower(ctxOptions.MetricName), "forward") { return nil } l := fl.Named("forward-metricsmodule") l.Info("Creating forward count metrics", zap.Any("options", ctxOptions)) - return &ForwardMetrics{ - baseMetricObject: newBaseMetricsObject(ctxOptions, fl, isLocalContext), - } + fm := ForwardMetrics{} + fm.baseMetricInterface = newBaseMetricsObject(ctxOptions, fl, isLocalContext, fm.expire, ttl) + return &fm } func (f *ForwardMetrics) Init(metricName string) { @@ -61,7 +62,7 @@ func (f *ForwardMetrics) Init(metricName string) { TotalBytesDesc, f.getLabels()...) default: - f.l.Error("unknown metric name", zap.String("name", metricName)) + f.getLogger().Error("unknown metric name", zap.String("name", metricName)) } f.metricName = metricName } @@ -71,21 +72,21 @@ func (f *ForwardMetrics) getLabels() []string { utils.Direction, } - if !f.advEnable { + if !f.isAdvanced() { return labels } - if f.srcCtx != nil { - labels = append(labels, f.srcCtx.getLabels()...) - f.l.Info("src labels", zap.Any("labels", labels)) + if f.sourceCtx() != nil { + labels = append(labels, f.sourceCtx().getLabels()...) + f.getLogger().Info("src labels", zap.Any("labels", labels)) } - if f.dstCtx != nil { - labels = append(labels, f.dstCtx.getLabels()...) - f.l.Info("dst labels", zap.Any("labels", labels)) + if f.destinationCtx() != nil { + labels = append(labels, f.destinationCtx().getLabels()...) + f.getLogger().Info("dst labels", zap.Any("labels", labels)) } - if slices.Contains(f.ctxOptions.AdditionalLabels, utils.IsReply) { + if slices.Contains(f.additionalLabels(), utils.IsReply) { labels = append(labels, utils.IsReply) } @@ -94,6 +95,7 @@ func (f *ForwardMetrics) getLabels() []string { func (f *ForwardMetrics) Clean() { exporter.UnregisterMetric(exporter.AdvancedRegistry, metricsinit.ToPrometheusType(f.forwardMetric)) + f.clean() } // TODO: update ProcessFlow with bytes metrics. We are only accounting for count. @@ -120,35 +122,35 @@ func (f *ForwardMetrics) ProcessFlow(flow *v1.Flow) { flow.TrafficDirection.String(), } - if !f.advEnable { + if !f.isAdvanced() { f.update(flow, labels) return } - if f.srcCtx != nil { - srcLabels := f.srcCtx.getValues(flow) + if f.sourceCtx() != nil { + srcLabels := f.sourceCtx().getValues(flow) if len(srcLabels) > 0 { labels = append(labels, srcLabels...) } } - if f.dstCtx != nil { - dstLabel := f.dstCtx.getValues(flow) + if f.destinationCtx() != nil { + dstLabel := f.destinationCtx().getValues(flow) if len(dstLabel) > 0 { labels = append(labels, dstLabel...) } } - if slices.Contains(f.ctxOptions.AdditionalLabels, utils.IsReply) { + if slices.Contains(f.additionalLabels(), utils.IsReply) { labels = append(labels, strconv.FormatBool(flow.GetIsReply().GetValue())) } f.update(flow, labels) - f.l.Debug("forward count metric is added", zap.Any("labels", labels)) + f.getLogger().Debug("forward count metric is added", zap.Any("labels", labels)) } func (f *ForwardMetrics) processLocalCtxFlow(flow *v1.Flow) { - labelValuesMap := f.srcCtx.getLocalCtxValues(flow) + labelValuesMap := f.sourceCtx().getLocalCtxValues(flow) if labelValuesMap == nil { return } @@ -156,22 +158,39 @@ func (f *ForwardMetrics) processLocalCtxFlow(flow *v1.Flow) { if len(labelValuesMap[ingress]) > 0 { labels := append([]string{ingress}, labelValuesMap[ingress]...) f.update(flow, labels) - f.l.Debug("forward count metric in INGRESS in local ctx", zap.Any("labels", labels)) + f.getLogger().Debug("forward count metric in INGRESS in local ctx", zap.Any("labels", labels)) } // Egress values. if len(labelValuesMap[egress]) > 0 { labels := append([]string{egress}, labelValuesMap[egress]...) f.update(flow, labels) - f.l.Debug("forward count metric in EGRESS in local ctx", zap.Any("labels", labels)) + f.getLogger().Debug("forward count metric in EGRESS in local ctx", zap.Any("labels", labels)) + } +} + +func (f *ForwardMetrics) expire(labels []string) bool { + var d bool + if f.forwardMetric != nil { + d = f.forwardMetric.DeleteLabelValues(labels...) + if d { + metricsinit.MetricsExpiredCounter.WithLabelValues(f.metricName).Inc() + } } + return d } func (f *ForwardMetrics) update(fl *v1.Flow, labels []string) { + var updated bool switch f.metricName { case utils.ForwardPacketsGaugeName: + updated = true f.forwardMetric.WithLabelValues(labels...).Add(float64(utils.PreviouslyObservedPackets(fl) + 1)) case utils.ForwardBytesGaugeName: + updated = true f.forwardMetric.WithLabelValues(labels...).Add(float64(utils.PacketSize(fl) + utils.PreviouslyObservedBytes(fl))) } + if updated { + f.updated(labels) + } } diff --git a/pkg/module/metrics/forward_test.go b/pkg/module/metrics/forward_test.go index 1af7558483..0c616c79b6 100644 --- a/pkg/module/metrics/forward_test.go +++ b/pkg/module/metrics/forward_test.go @@ -6,6 +6,7 @@ package metrics import ( "testing" + "time" "github.com/cilium/cilium/api/v1/flow" "github.com/microsoft/retina/crd/api/v1alpha1" @@ -26,6 +27,7 @@ type TestMetrics struct { metricCall int nilObj bool localContext enrichmentContext + trackedMetrics int } func TestNewForward(t *testing.T) { @@ -53,6 +55,7 @@ func TestNewForward(t *testing.T) { }, exepectedLabels: []string{"direction"}, metricCall: 1, + trackedMetrics: 1, }, { name: "plain opts with nil flow", @@ -108,7 +111,8 @@ func TestNewForward(t *testing.T) { "source_service", "source_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "dest opts 1", @@ -130,7 +134,8 @@ func TestNewForward(t *testing.T) { "destination_service", "destination_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "source opts with flow", @@ -153,7 +158,8 @@ func TestNewForward(t *testing.T) { "source_service", "source_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "drop source opts expect nil", @@ -223,8 +229,9 @@ func TestNewForward(t *testing.T) { "service", "port", }, - metricCall: 1, - localContext: localContext, + metricCall: 1, + trackedMetrics: 1, + localContext: localContext, }, { name: "dest opts 1 with flow in local context", @@ -247,8 +254,9 @@ func TestNewForward(t *testing.T) { "service", "port", }, - metricCall: 1, - localContext: localContext, + metricCall: 1, + trackedMetrics: 1, + localContext: localContext, }, { name: "src and dest opts 1 with flow in local context", @@ -272,8 +280,9 @@ func TestNewForward(t *testing.T) { "service", "port", }, - metricCall: 2, - localContext: localContext, + metricCall: 2, + trackedMetrics: 2, + localContext: localContext, }, { name: "src and dest opts 1 with flow in local context and is_reply", @@ -299,8 +308,9 @@ func TestNewForward(t *testing.T) { "port", "is_reply", }, - metricCall: 2, - localContext: localContext, + metricCall: 2, + trackedMetrics: 2, + localContext: localContext, }, } @@ -309,7 +319,7 @@ func TestNewForward(t *testing.T) { l.Info("Running test", zap.String("name", tc.name), zap.String("metricName", metricName)) ctrl := gomock.NewController(t) - f := NewForwardCountMetrics(tc.opts, log.Logger(), tc.localContext) + f := NewForwardCountMetrics(tc.opts, log.Logger(), tc.localContext, time.Duration(0)) if tc.nilObj { assert.Nil(t, f, "forward metrics should be nil Test Name: %s", tc.name) continue @@ -326,11 +336,40 @@ func TestNewForward(t *testing.T) { Help: "testmetric", }) forwardMock.EXPECT().WithLabelValues(gomock.Any()).Return(testmetric).Times(tc.metricCall) - assert.Equal(t, f.advEnable, tc.checkIsAdvance, "advance metrics options should be equal Test Name: %s", tc.name) + assert.Equal(t, f.isAdvanced(), tc.checkIsAdvance, "advance metrics options should be equal Test Name: %s", tc.name) assert.Equal(t, tc.exepectedLabels, f.getLabels(), "labels should be equal Test Name: %s", tc.name) f.metricName = metricName f.ProcessFlow(tc.f) + + // There should be no tracked metrics when TTL is infinite + assert.Equal(t, 0, len(f.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite Test Name: %s", tc.name) + + // Test TTL based expiration + metricsinit.InitializeMetrics() + + // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics + f = NewForwardCountMetrics(tc.opts, log.Logger(), tc.localContext, time.Minute) + f.forwardMetric = forwardMock + + forwardMock.EXPECT().WithLabelValues(gomock.Any()).Return(testmetric).Times(tc.metricCall) + + f.metricName = metricName + f.ProcessFlow(tc.f) + + forwardMock.EXPECT().DeleteLabelValues(gomock.Any()).Return(true).Times(tc.trackedMetrics) + + for _, ls := range f.trackedMetricLabels() { + assert.True(t, f.expire(ls), "metric should expire successfully Test Name: %s", tc.name) + } + + // Test that clean calls the base object + baseMetricObjectMock := NewMockbaseMetricInterface(ctrl) + f.baseMetricInterface = baseMetricObjectMock + + baseMetricObjectMock.EXPECT().clean().Times(1) + + f.Clean() ctrl.Finish() } } diff --git a/pkg/module/metrics/metrics_module.go b/pkg/module/metrics/metrics_module.go index 0d38c06522..617ce74475 100644 --- a/pkg/module/metrics/metrics_module.go +++ b/pkg/module/metrics/metrics_module.go @@ -221,23 +221,33 @@ func (m *Module) updateMetricsContexts(spec *api.MetricsSpec) { } for _, ctxOption := range spec.ContextOptions { + var ttl time.Duration + var err error + if ctxOption.TTL != "" { + ttl, err = time.ParseDuration(ctxOption.TTL) + // this shouldn't happen since we've already validated the CRD, but put some safety here just in case + if err != nil { + m.l.Error("Invalid TTL format", zap.String("metricName", ctxOption.MetricName), zap.Error(err)) + continue + } + } switch { case strings.Contains(ctxOption.MetricName, forward): - fm := NewForwardCountMetrics(&ctxOption, m.l, ctxType) + fm := NewForwardCountMetrics(&ctxOption, m.l, ctxType, ttl) if fm != nil { m.registry[ctxOption.MetricName] = fm } case strings.Contains(ctxOption.MetricName, drop): - dm := NewDropCountMetrics(&ctxOption, m.l, ctxType) + dm := NewDropCountMetrics(&ctxOption, m.l, ctxType, ttl) if dm != nil { m.registry[ctxOption.MetricName] = dm } case strings.Contains(ctxOption.MetricName, tcp): - tm := NewTCPMetrics(&ctxOption, m.l, ctxType) + tm := NewTCPMetrics(&ctxOption, m.l, ctxType, ttl) if tm != nil { m.registry[ctxOption.MetricName] = tm } - tr := NewTCPRetransMetrics(&ctxOption, m.l, ctxType) + tr := NewTCPRetransMetrics(&ctxOption, m.l, ctxType, ttl) if tr != nil { m.registry[ctxOption.MetricName] = tr } @@ -249,7 +259,7 @@ func (m *Module) updateMetricsContexts(spec *api.MetricsSpec) { m.registry[nodeApiserver] = lm } case strings.Contains(ctxOption.MetricName, dns) || strings.Contains(ctxOption.MetricName, pktmon): - dm := NewDNSMetrics(&ctxOption, m.l, ctxType) + dm := NewDNSMetrics(&ctxOption, m.l, ctxType, ttl) if dm != nil { m.registry[ctxOption.MetricName] = dm } diff --git a/pkg/module/metrics/metrics_module_linux_test.go b/pkg/module/metrics/metrics_module_linux_test.go index 1d53ac4b54..d6bd597efa 100644 --- a/pkg/module/metrics/metrics_module_linux_test.go +++ b/pkg/module/metrics/metrics_module_linux_test.go @@ -373,7 +373,7 @@ func TestModule_Reconcile(t *testing.T) { l := log.Logger().Named("test") testDropMetric := &DropCountMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ advEnable: true, ctxOptions: &api.MetricsContextOptions{ MetricName: "drop_count", @@ -385,7 +385,7 @@ func TestModule_Reconcile(t *testing.T) { } testDropMetric.Init("drop_count") testDropMetricBytes := &DropCountMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ advEnable: true, ctxOptions: &api.MetricsContextOptions{ MetricName: "drop_bytes", @@ -395,7 +395,7 @@ func TestModule_Reconcile(t *testing.T) { } testDropMetricBytes.Init("drop_bytes") testForwardMetric := &ForwardMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ advEnable: true, ctxOptions: &api.MetricsContextOptions{ MetricName: "forward_count", @@ -407,7 +407,7 @@ func TestModule_Reconcile(t *testing.T) { } testForwardMetric.Init("forward_count") testForwardMetricBytes := &ForwardMetrics{ - baseMetricObject: baseMetricObject{ + baseMetricInterface: &baseMetricObject{ advEnable: true, ctxOptions: &api.MetricsContextOptions{ MetricName: "forward_bytes", diff --git a/pkg/module/metrics/mock_basemetricsobject.go b/pkg/module/metrics/mock_basemetricsobject.go new file mode 100644 index 0000000000..f00d0b510f --- /dev/null +++ b/pkg/module/metrics/mock_basemetricsobject.go @@ -0,0 +1,162 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: basemetricsobject.go +// +// Generated by this command: +// +// mockgen -source=basemetricsobject.go -destination=mock_basemetricsobject.go -package=metrics +// + +// Package metrics is a generated GoMock package. +package metrics + +import ( + reflect "reflect" + + log "github.com/microsoft/retina/pkg/log" + gomock "go.uber.org/mock/gomock" +) + +// MockbaseMetricInterface is a mock of baseMetricInterface interface. +type MockbaseMetricInterface struct { + ctrl *gomock.Controller + recorder *MockbaseMetricInterfaceMockRecorder +} + +// MockbaseMetricInterfaceMockRecorder is the mock recorder for MockbaseMetricInterface. +type MockbaseMetricInterfaceMockRecorder struct { + mock *MockbaseMetricInterface +} + +// NewMockbaseMetricInterface creates a new mock instance. +func NewMockbaseMetricInterface(ctrl *gomock.Controller) *MockbaseMetricInterface { + mock := &MockbaseMetricInterface{ctrl: ctrl} + mock.recorder = &MockbaseMetricInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockbaseMetricInterface) EXPECT() *MockbaseMetricInterfaceMockRecorder { + return m.recorder +} + +// additionalLabels mocks base method. +func (m *MockbaseMetricInterface) additionalLabels() []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "additionalLabels") + ret0, _ := ret[0].([]string) + return ret0 +} + +// additionalLabels indicates an expected call of additionalLabels. +func (mr *MockbaseMetricInterfaceMockRecorder) additionalLabels() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "additionalLabels", reflect.TypeOf((*MockbaseMetricInterface)(nil).additionalLabels)) +} + +// clean mocks base method. +func (m *MockbaseMetricInterface) clean() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "clean") +} + +// clean indicates an expected call of clean. +func (mr *MockbaseMetricInterfaceMockRecorder) clean() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "clean", reflect.TypeOf((*MockbaseMetricInterface)(nil).clean)) +} + +// destinationCtx mocks base method. +func (m *MockbaseMetricInterface) destinationCtx() ContextOptionsInterface { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "destinationCtx") + ret0, _ := ret[0].(ContextOptionsInterface) + return ret0 +} + +// destinationCtx indicates an expected call of destinationCtx. +func (mr *MockbaseMetricInterfaceMockRecorder) destinationCtx() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "destinationCtx", reflect.TypeOf((*MockbaseMetricInterface)(nil).destinationCtx)) +} + +// getLogger mocks base method. +func (m *MockbaseMetricInterface) getLogger() *log.ZapLogger { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "getLogger") + ret0, _ := ret[0].(*log.ZapLogger) + return ret0 +} + +// getLogger indicates an expected call of getLogger. +func (mr *MockbaseMetricInterfaceMockRecorder) getLogger() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getLogger", reflect.TypeOf((*MockbaseMetricInterface)(nil).getLogger)) +} + +// isAdvanced mocks base method. +func (m *MockbaseMetricInterface) isAdvanced() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "isAdvanced") + ret0, _ := ret[0].(bool) + return ret0 +} + +// isAdvanced indicates an expected call of isAdvanced. +func (mr *MockbaseMetricInterfaceMockRecorder) isAdvanced() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "isAdvanced", reflect.TypeOf((*MockbaseMetricInterface)(nil).isAdvanced)) +} + +// isLocalContext mocks base method. +func (m *MockbaseMetricInterface) isLocalContext() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "isLocalContext") + ret0, _ := ret[0].(bool) + return ret0 +} + +// isLocalContext indicates an expected call of isLocalContext. +func (mr *MockbaseMetricInterfaceMockRecorder) isLocalContext() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "isLocalContext", reflect.TypeOf((*MockbaseMetricInterface)(nil).isLocalContext)) +} + +// sourceCtx mocks base method. +func (m *MockbaseMetricInterface) sourceCtx() ContextOptionsInterface { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "sourceCtx") + ret0, _ := ret[0].(ContextOptionsInterface) + return ret0 +} + +// sourceCtx indicates an expected call of sourceCtx. +func (mr *MockbaseMetricInterfaceMockRecorder) sourceCtx() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "sourceCtx", reflect.TypeOf((*MockbaseMetricInterface)(nil).sourceCtx)) +} + +// trackedMetricLabels mocks base method. +func (m *MockbaseMetricInterface) trackedMetricLabels() [][]string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "trackedMetricLabels") + ret0, _ := ret[0].([][]string) + return ret0 +} + +// trackedMetricLabels indicates an expected call of trackedMetricLabels. +func (mr *MockbaseMetricInterfaceMockRecorder) trackedMetricLabels() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "trackedMetricLabels", reflect.TypeOf((*MockbaseMetricInterface)(nil).trackedMetricLabels)) +} + +// updated mocks base method. +func (m *MockbaseMetricInterface) updated(lbs []string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "updated", lbs) +} + +// updated indicates an expected call of updated. +func (mr *MockbaseMetricInterfaceMockRecorder) updated(lbs any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "updated", reflect.TypeOf((*MockbaseMetricInterface)(nil).updated), lbs) +} diff --git a/pkg/module/metrics/tcpflags.go b/pkg/module/metrics/tcpflags.go index c6a24a8635..9114ca4d13 100644 --- a/pkg/module/metrics/tcpflags.go +++ b/pkg/module/metrics/tcpflags.go @@ -5,6 +5,7 @@ package metrics import ( "strings" + "time" v1 "github.com/cilium/cilium/api/v1/flow" api "github.com/microsoft/retina/crd/api/v1alpha1" @@ -24,20 +25,20 @@ const ( ) type TCPMetrics struct { - baseMetricObject + baseMetricInterface tcpFlagsMetrics metricsinit.GaugeVec } -func NewTCPMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext) *TCPMetrics { +func NewTCPMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext, ttl time.Duration) *TCPMetrics { if ctxOptions == nil || !strings.Contains(strings.ToLower(ctxOptions.MetricName), "flag") { return nil } fl = fl.Named("tcpflags-metricsmodule") fl.Info("Creating TCP Flags count metrics", zap.Any("options", ctxOptions)) - return &TCPMetrics{ - baseMetricObject: newBaseMetricsObject(ctxOptions, fl, isLocalContext), - } + t := &TCPMetrics{} + t.baseMetricInterface = newBaseMetricsObject(ctxOptions, fl, isLocalContext, t.expire, ttl) + return t } func (t *TCPMetrics) Init(metricName string) { @@ -54,12 +55,12 @@ func (t *TCPMetrics) getLabels() []string { labels := []string{ utils.Flag, } - if t.srcCtx != nil { - labels = append(labels, t.srcCtx.getLabels()...) + if t.sourceCtx() != nil { + labels = append(labels, t.sourceCtx().getLabels()...) } - if t.dstCtx != nil { - labels = append(labels, t.dstCtx.getLabels()...) + if t.destinationCtx() != nil { + labels = append(labels, t.destinationCtx().getLabels()...) } return labels @@ -113,24 +114,24 @@ func (t *TCPMetrics) ProcessFlow(flow *v1.Flow) { } var srcLabels, dstLabels []string - if t.srcCtx != nil { - srcLabels = t.srcCtx.getValues(flow) + if t.sourceCtx() != nil { + srcLabels = t.sourceCtx().getValues(flow) } - if t.dstCtx != nil { - dstLabels = t.dstCtx.getValues(flow) + if t.destinationCtx() != nil { + dstLabels = t.destinationCtx().getValues(flow) } for flag, count := range combineFlagsWithPrevious(flags, flow) { labels := append([]string{flag}, srcLabels...) labels = append(labels, dstLabels...) - t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) - t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) + t.update(labels, count) + t.getLogger().Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) } } func (t *TCPMetrics) processLocalCtxFlow(flow *v1.Flow, flags []string) { - labelValuesMap := t.srcCtx.getLocalCtxValues(flow) + labelValuesMap := t.sourceCtx().getLocalCtxValues(flow) if labelValuesMap == nil { return } @@ -141,20 +142,36 @@ func (t *TCPMetrics) processLocalCtxFlow(flow *v1.Flow, flags []string) { if l := len(labelValuesMap[ingress]); l > 0 { for flag, count := range combinedFlags { labels := append([]string{flag}, labelValuesMap[ingress]...) - t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) - t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) + t.update(labels, count) + t.getLogger().Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) } } if l := len(labelValuesMap[egress]); l > 0 { for flag, count := range combinedFlags { labels := append([]string{flag}, labelValuesMap[egress]...) - t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) - t.l.Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) + t.update(labels, count) + t.getLogger().Debug("TCP flag metric", zap.String("flag", flag), zap.Strings("labels", labels), zap.Uint32("count", count)) } } } +func (t *TCPMetrics) expire(labels []string) bool { + var d bool + if t.tcpFlagsMetrics != nil { + d = t.tcpFlagsMetrics.DeleteLabelValues(labels...) + if d { + metricsinit.MetricsExpiredCounter.WithLabelValues(TCPFlagsCountName).Inc() + } + } + return d +} + +func (t *TCPMetrics) update(labels []string, count uint32) { + t.tcpFlagsMetrics.WithLabelValues(labels...).Add(float64(count)) + t.updated(labels) +} + func (t *TCPMetrics) getFlagValues(flags *v1.TCPFlags) []string { f := make([]string, 0) if flags == nil { @@ -204,4 +221,5 @@ func (t *TCPMetrics) getFlagValues(flags *v1.TCPFlags) []string { func (t *TCPMetrics) Clean() { exporter.UnregisterMetric(exporter.AdvancedRegistry, metricsinit.ToPrometheusType(t.tcpFlagsMetrics)) + t.clean() } diff --git a/pkg/module/metrics/tcpflags_test.go b/pkg/module/metrics/tcpflags_test.go index 8b845df6bb..16ad91a326 100644 --- a/pkg/module/metrics/tcpflags_test.go +++ b/pkg/module/metrics/tcpflags_test.go @@ -6,6 +6,7 @@ package metrics import ( "testing" + "time" "github.com/cilium/cilium/api/v1/flow" "github.com/microsoft/retina/crd/api/v1alpha1" @@ -159,7 +160,8 @@ func TestNewTCPMetrics(t *testing.T) { "source_service", "source_port", }, - metricCall: 1, + metricCall: 1, + trackedMetrics: 1, }, { name: "source opts with nil flow", @@ -227,7 +229,8 @@ func TestNewTCPMetrics(t *testing.T) { "source_service", "source_port", }, - metricCall: 7, + metricCall: 7, + trackedMetrics: 7, }, { name: "dest opts with flow with all flags ", @@ -266,7 +269,8 @@ func TestNewTCPMetrics(t *testing.T) { "destination_service", "destination_port", }, - metricCall: 7, + metricCall: 7, + trackedMetrics: 7, }, { name: "dest opts with flow with all but syn flags ", @@ -304,7 +308,8 @@ func TestNewTCPMetrics(t *testing.T) { "destination_service", "destination_port", }, - metricCall: 7, + metricCall: 7, + trackedMetrics: 7, }, { name: "dest opts with flow with all flags dropped verdict", @@ -382,8 +387,9 @@ func TestNewTCPMetrics(t *testing.T) { "service", "port", }, - localContext: localContext, - metricCall: 7, + localContext: localContext, + metricCall: 7, + trackedMetrics: 7, }, { name: "local ctx dest opts with flow with all flags ", @@ -462,8 +468,9 @@ func TestNewTCPMetrics(t *testing.T) { "service", "port", }, - localContext: localContext, - metricCall: 14, + localContext: localContext, + metricCall: 14, + trackedMetrics: 7, }, } @@ -471,7 +478,7 @@ func TestNewTCPMetrics(t *testing.T) { log.Logger().Info("Running test name", zap.String("name", tc.name)) ctrl := gomock.NewController(t) - tcp := NewTCPMetrics(tc.opts, log.Logger(), tc.localContext) + tcp := NewTCPMetrics(tc.opts, log.Logger(), tc.localContext, time.Duration(0)) if tc.nilObj { assert.Nil(t, tcp, "forward metrics should be nil Test Name: %s", tc.name) continue @@ -488,10 +495,37 @@ func TestNewTCPMetrics(t *testing.T) { }) tcpFlagMockMetrics.EXPECT().WithLabelValues(gomock.Any()).Return(testmetric).Times(tc.metricCall) - assert.Equal(t, tc.checkIsAdvance, tcp.advEnable, "IsAdvance should be %v Test Name: %s", tc.checkIsAdvance, tc.name) + assert.Equal(t, tc.checkIsAdvance, tcp.isAdvanced(), "IsAdvance should be %v Test Name: %s", tc.checkIsAdvance, tc.name) assert.Equal(t, tc.exepectedLabels, tcp.getLabels(), "labels should be %v Test Name: %s", tc.exepectedLabels, tc.name) tcp.ProcessFlow(tc.f) + + assert.Equal(t, 0, len(tcp.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite Test Name: %s", tc.name) + + // Test TTL based expiration + metricsinit.InitializeMetrics() + + // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics + tcp = NewTCPMetrics(tc.opts, log.Logger(), tc.localContext, time.Minute) + tcp.tcpFlagsMetrics = tcpFlagMockMetrics + + tcpFlagMockMetrics.EXPECT().WithLabelValues(gomock.Any()).Return(testmetric).Times(tc.metricCall) + + tcp.ProcessFlow(tc.f) + + tcpFlagMockMetrics.EXPECT().DeleteLabelValues(gomock.Any()).Return(true).Times(tc.trackedMetrics) + + for _, ls := range tcp.trackedMetricLabels() { + assert.True(t, tcp.expire(ls), "metric should expire successfully Test Name: %s", tc.name) + } + + // Test that clean calls the base object + baseMetricObjectMock := NewMockbaseMetricInterface(ctrl) + tcp.baseMetricInterface = baseMetricObjectMock + + baseMetricObjectMock.EXPECT().clean().Times(1) + + tcp.Clean() ctrl.Finish() } } diff --git a/pkg/module/metrics/tcpretrans.go b/pkg/module/metrics/tcpretrans.go index 3e307eabf4..623fbcf933 100644 --- a/pkg/module/metrics/tcpretrans.go +++ b/pkg/module/metrics/tcpretrans.go @@ -5,6 +5,7 @@ package metrics import ( "strings" + "time" v1 "github.com/cilium/cilium/api/v1/flow" api "github.com/microsoft/retina/crd/api/v1alpha1" @@ -24,20 +25,20 @@ const ( ) type TCPRetransMetrics struct { - baseMetricObject + baseMetricInterface tcpRetransMetrics metricsinit.GaugeVec } -func NewTCPRetransMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext) *TCPRetransMetrics { +func NewTCPRetransMetrics(ctxOptions *api.MetricsContextOptions, fl *log.ZapLogger, isLocalContext enrichmentContext, ttl time.Duration) *TCPRetransMetrics { if ctxOptions == nil || !strings.Contains(strings.ToLower(ctxOptions.MetricName), "retrans") { return nil } fl = fl.Named("tcpretrans-metricsmodule") fl.Info("Creating TCP retransmit count metrics", zap.Any("options", ctxOptions)) - return &TCPRetransMetrics{ - baseMetricObject: newBaseMetricsObject(ctxOptions, fl, isLocalContext), - } + t := &TCPRetransMetrics{} + t.baseMetricInterface = newBaseMetricsObject(ctxOptions, fl, isLocalContext, t.expire, ttl) + return t } func (t *TCPRetransMetrics) Init(metricName string) { @@ -52,14 +53,14 @@ func (t *TCPRetransMetrics) Init(metricName string) { func (t *TCPRetransMetrics) getLabels() []string { labels := []string{utils.Direction} - if t.srcCtx != nil { - labels = append(labels, t.srcCtx.getLabels()...) - t.l.Info("src labels", zap.Any("labels", labels)) + if t.sourceCtx() != nil { + labels = append(labels, t.sourceCtx().getLabels()...) + t.getLogger().Info("src labels", zap.Any("labels", labels)) } - if t.dstCtx != nil { - labels = append(labels, t.dstCtx.getLabels()...) - t.l.Info("dst labels", zap.Any("labels", labels)) + if t.destinationCtx() != nil { + labels = append(labels, t.destinationCtx().getLabels()...) + t.getLogger().Info("dst labels", zap.Any("labels", labels)) } return labels @@ -82,42 +83,59 @@ func (t *TCPRetransMetrics) ProcessFlow(flow *v1.Flow) { } labels := []string{flow.TrafficDirection.String()} - if t.srcCtx != nil { - srcLabels := t.srcCtx.getValues(flow) + if t.sourceCtx() != nil { + srcLabels := t.sourceCtx().getValues(flow) if len(srcLabels) > 0 { labels = append(labels, srcLabels...) } } - if t.dstCtx != nil { - dstLabels := t.dstCtx.getValues(flow) + if t.destinationCtx() != nil { + dstLabels := t.destinationCtx().getValues(flow) if len(dstLabels) > 0 { labels = append(labels, dstLabels...) } } - t.tcpRetransMetrics.WithLabelValues(labels...).Inc() + t.update(labels) } func (t *TCPRetransMetrics) processLocalCtxFlow(flow *v1.Flow) { - labelValuesMap := t.srcCtx.getLocalCtxValues(flow) + labelValuesMap := t.sourceCtx().getLocalCtxValues(flow) if labelValuesMap == nil { return } if len(labelValuesMap[ingress]) > 0 { labels := append([]string{ingress}, labelValuesMap[ingress]...) - t.tcpRetransMetrics.WithLabelValues(labels...).Inc() - t.l.Debug("tcp retransmission count metric in INGRESS in local ctx", zap.Any("labels", labels)) + t.update(labels) + t.getLogger().Debug("tcp retransmission count metric in INGRESS in local ctx", zap.Any("labels", labels)) } if len(labelValuesMap[egress]) > 0 { labels := append([]string{egress}, labelValuesMap[egress]...) - t.tcpRetransMetrics.WithLabelValues(labels...).Inc() - t.l.Debug("tcp retransmission count metric in EGRESS in local ctx", zap.Any("labels", labels)) + t.update(labels) + t.getLogger().Debug("tcp retransmission count metric in EGRESS in local ctx", zap.Any("labels", labels)) } } +func (t *TCPRetransMetrics) expire(labels []string) bool { + var d bool + if t.tcpRetransMetrics != nil { + d = t.tcpRetransMetrics.DeleteLabelValues(labels...) + if d { + metricsinit.MetricsExpiredCounter.WithLabelValues(TCPRetransCountName).Inc() + } + } + return d +} + +func (t *TCPRetransMetrics) update(labels []string) { + t.tcpRetransMetrics.WithLabelValues(labels...).Inc() + t.updated(labels) +} + func (t *TCPRetransMetrics) Clean() { exporter.UnregisterMetric(exporter.AdvancedRegistry, metricsinit.ToPrometheusType(t.tcpRetransMetrics)) + t.clean() } diff --git a/pkg/utils/attr_utils.go b/pkg/utils/attr_utils.go index eac816e88f..5223b34772 100644 --- a/pkg/utils/attr_utils.go +++ b/pkg/utils/attr_utils.go @@ -47,6 +47,7 @@ var ( AclRule = "aclrule" Active = "ACTIVE" Device = "device" + Metric = "metric" // TCP Connection Statistic Names ResetCount = "ResetCount" From ac63721b070d353449aca6414cd7cc2031875cf0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 01:25:35 -0500 Subject: [PATCH 216/448] deps: bump helm/kind-action from 1.13.0 to 1.14.0 (#2068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.13.0 to 1.14.0.
Release notes

Sourced from helm/kind-action's releases.

v1.14.0

What's Changed

New Contributors

Full Changelog: https://github.com/helm/kind-action/compare/v1...v1.14.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=helm/kind-action&package-manager=github_actions&previous-version=1.13.0&new-version=1.14.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-validation.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-validation.yaml b/.github/workflows/release-validation.yaml index 6f53292b3e..e6b1506e86 100644 --- a/.github/workflows/release-validation.yaml +++ b/.github/workflows/release-validation.yaml @@ -45,7 +45,7 @@ jobs: helm pull oci://ghcr.io/microsoft/retina/charts/retina --version ${{ env.TAG }} - name: Setup kind cluster - uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0 + uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0 # krew does not support installing a specific verison # so if this step fails it means there was something wrong From 9585b8f26bdd6d3bf3430559c2bbe38c220ef93a Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:49:50 +0000 Subject: [PATCH 217/448] refactor: Drop Windows Server 2019 support (#2076) ## Summary - remove Windows Server 2019 support across build/test targets - align Windows image defaults to 2022+ and update manifests - clean up related CLI mappings, scripts, and docs ## Changes - drop 2019 from Windows build matrices and manifest targets - remove Windows 2019 Dockerfiles and base image references - remove 2019 OS image mapping and tests in capture download - update AKS deploy script and README note - update image metadata artifacts to remove ltsc2019 ## Testing - not run (not requested) ## Notes - Windows builds remain enabled for 2022+ only ## Related Issue - Fixes #2075 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes -This PR is required to unblock CI, see for example https://github.com/microsoft/retina/actions/runs/22350794227/job/64686829439 --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- Makefile | 7 +++--- README.md | 2 ++ cli/cmd/capture/download.go | 2 -- cli/cmd/capture/download_test.go | 5 ---- controller/Dockerfile.windows-2019 | 24 ------------------ .../Dockerfile.windows-retina-oss-build | 3 --- .../prometheus/deploy-retina-clusters.sh | 10 -------- operator/Dockerfile.windows-2019 | 25 ------------------- 10 files changed, 7 insertions(+), 75 deletions(-) delete mode 100644 controller/Dockerfile.windows-2019 delete mode 100644 operator/Dockerfile.windows-2019 diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 5a5cae012c..52fc7c9a9f 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -124,7 +124,7 @@ jobs: strategy: matrix: - year: ["2019", "2022"] + year: ["2022"] platform: ["windows"] arch: ["amd64"] diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index d3f7f436fc..5b55e82e4d 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -100,7 +100,7 @@ jobs: strategy: matrix: - year: ["2019", "2022"] + year: ["2022"] platform: ["windows"] arch: ["amd64"] diff --git a/Makefile b/Makefile index 70f120886c..4cfccff752 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,6 @@ CAPTURE_WORKLOAD_DIR = $(REPO_ROOT)/captureworkload KIND = /usr/local/bin/kind KIND_CLUSTER = retina-cluster WINVER2022 ?= "10.0.20348.1906" -WINVER2019 ?= "10.0.17763.4737" APP_INSIGHTS_ID ?= "" AGENT_IMAGE_NAME ?= "" GENERATE_TARGET_DIRS = \ @@ -40,7 +39,7 @@ OS ?= $(GOOS) ARCH ?= $(GOARCH) PLATFORM ?= $(OS)/$(ARCH) PLATFORMS ?= linux/amd64 linux/arm64 windows/amd64 -OS_VERSION ?= ltsc2019 +OS_VERSION ?= ltsc2022 HUBBLE_VERSION ?= v1.18.6 @@ -68,7 +67,7 @@ RETINA_PLATFORM_TAG ?= $(TAG)-$(subst /,-,$(PLATFORM)) # used for looping through components in container build AGENT_TARGETS ?= init agent -WINDOWS_YEARS ?= 2019 2022 +WINDOWS_YEARS ?= 2022 # for windows os, add year to the platform tag ifeq ($(OS),windows) @@ -407,7 +406,7 @@ build-windows-binaries: ## Build Windows binaries manifest-retina-image: ## create a multiplatform manifest for the retina image $(eval FULL_IMAGE_NAME=$(IMAGE_REGISTRY)/$(RETINA_IMAGE):$(TAG)) $(eval FULL_INIT_IMAGE_NAME=$(IMAGE_REGISTRY)/$(RETINA_INIT_IMAGE):$(TAG)) - docker buildx imagetools create -t $(FULL_IMAGE_NAME) $(foreach platform,linux/amd64 linux/arm64 windows-ltsc2019-amd64 windows-ltsc2022-amd64, $(FULL_IMAGE_NAME)-$(subst /,-,$(platform))) + docker buildx imagetools create -t $(FULL_IMAGE_NAME) $(foreach platform,linux/amd64 linux/arm64 windows-ltsc2022-amd64, $(FULL_IMAGE_NAME)-$(subst /,-,$(platform))) docker buildx imagetools create -t $(FULL_INIT_IMAGE_NAME) $(foreach platform,linux/amd64 linux/arm64, $(FULL_INIT_IMAGE_NAME)-$(subst /,-,$(platform))) manifest-operator-image: ## create a multiplatform manifest for the operator image diff --git a/README.md b/README.md index caa68e427b..541b5f930f 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ See [retina.sh](http://retina.sh) for documentation and examples. ⚠️ **Performance on High-Core-Count Systems**: Community users have reported performance considerations when using Advanced metrics (with `packetparser` plugin) on nodes with 32+ CPU cores under high network load. Consider starting with Basic metrics mode on large node types. See [Known Limitations](https://retina.sh/docs/Introduction/intro#known-limitations) for details. +⚠️ **Windows Server 2019**: Retina no longer supports Windows Server 2019 nodes. Use Windows Server 2022 for Windows workloads. + ## Capabilities Retina has two major features: diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index 9729ad4764..910608c51a 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -185,8 +185,6 @@ func getWindowsContainerImage(node *corev1.Node) string { suffix = "ltsc2025" case strings.Contains(osImage, "2022"): suffix = "ltsc2022" - case strings.Contains(osImage, "2019"): - suffix = "ltsc2019" case strings.Contains(osImage, "2016"): suffix = "ltsc2016" default: diff --git a/cli/cmd/capture/download_test.go b/cli/cmd/capture/download_test.go index 4769d4b348..1609d60796 100644 --- a/cli/cmd/capture/download_test.go +++ b/cli/cmd/capture/download_test.go @@ -390,11 +390,6 @@ func TestGetWindowsContainerImage(t *testing.T) { osImage: "Windows Server 2022 Datacenter", expectedSuffix: "ltsc2022", }, - { - name: "Windows Server 2019", - osImage: "Windows Server 2019 Datacenter", - expectedSuffix: "ltsc2019", - }, { name: "Windows Server 2025", osImage: "Windows Server 2025 Datacenter", diff --git a/controller/Dockerfile.windows-2019 b/controller/Dockerfile.windows-2019 deleted file mode 100644 index f54fca399b..0000000000 --- a/controller/Dockerfile.windows-2019 +++ /dev/null @@ -1,24 +0,0 @@ -# pinned base image -# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca AS ltsc2019 - -FROM ltsc2019 AS agent-win -ARG GOARCH=amd64 # default to amd64 -ARG GOOS=windows # default to windows -ARG OS_VERSION=ltsc2019 -ARG REPO_PATH -ARG BINARIES_PATH -ENV GOARCH=${GOARCH} -ENV GOOS=${GOOS} -ENV OS_VERSION=${OS_VERSION} -ENV BINARIES_PATH=${BINARIES_PATH} -ENV REPO_PATH=${REPO_PATH} -# CVE-2013-3900 Mitigation -RUN reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f -RUN reg add "HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Cryptography\Wintrust\Config" /v "EnableCertPaddingCheck" /t REG_DWORD /d "1" /f -COPY ${REPO_PATH}/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml -COPY ${REPO_PATH}/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 -COPY ${BINARIES_PATH}/captureworkload.exe captureworkload.exe -COPY ${BINARIES_PATH}/controller.exe controller.exe -ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe -CMD ["controller.exe", "start", "--kubeconfig=.\\kubeconfig"] diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index d6c7332fff..8a1f5be288 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -2,9 +2,6 @@ ARG OS_VERSION=ltsc2022 # pinned base images -# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a3d7773c4a836c2efd3ecb89f4fcb41199ee56d454225cf72a65b603bf569eca AS ltsc2019 - # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 diff --git a/deploy/standard/prometheus/deploy-retina-clusters.sh b/deploy/standard/prometheus/deploy-retina-clusters.sh index 1c74a989c5..82f922fd9c 100755 --- a/deploy/standard/prometheus/deploy-retina-clusters.sh +++ b/deploy/standard/prometheus/deploy-retina-clusters.sh @@ -65,16 +65,6 @@ az aks nodepool add \ --os-sku Windows2022 \ --node-count 1 -# Set variables for Windows 2019 node pool -myWindowsNodePool="nwin19" # Length <= 6 -az aks nodepool add \ - --resource-group $RESOURCE_GROUP \ - --cluster-name $NAME \ - --name $myWindowsNodePool \ - --os-type Windows \ - --os-sku Windows2019 \ - --node-count 1 - az aks get-credentials -g $RESOURCE_GROUP -n $NAME --overwrite-existing kubectl apply -f ama-metrics-settings-configmap.yaml diff --git a/operator/Dockerfile.windows-2019 b/operator/Dockerfile.windows-2019 deleted file mode 100644 index 0fbae1b92e..0000000000 --- a/operator/Dockerfile.windows-2019 +++ /dev/null @@ -1,25 +0,0 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder - -# Build args -ARG VERSION -ARG APP_INSIGHTS_ID - -ENV GOOS=windows -ENV GOARCH=amd64 - -WORKDIR /usr/src/retina -# Copy the source -COPY . . - -RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID"" -o -o /usr/bin/retina-operator.exe retina-operator operator/main.go - -# Copy into final image -# skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2019 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:244f1c6f590ca5a417c241a11cd6719a456f9771c45a0c2b195d5636763a7f0e -COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml -COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 - -COPY --from=builder /usr/bin/retina-operator.exe retina-operator.exe - -CMD ["controller.exe", "start", "--kubeconfig=.\\kubeconfig"] From 001c2bab1df57f32a0b523ab20ca9e3c0185e333 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 25 Feb 2026 08:23:02 -0500 Subject: [PATCH 218/448] fix(ci): fix markdownlint config not being applied after v22 action bump (#2067) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The v9 → v22 bump of `markdownlint-cli2-action` in #2060 broke the Markdown Lint CI check for all PRs. The `command` input was removed in v22 and replaced with a dedicated `config` input. The old invocation silently ignored both `command: config` and the config file path inside `globs`, causing all files to be linted with default rules — including MD013 (line-length) which the project explicitly disables in `.github/.markdownlint.json`. This PR switches to the v22 `config` input so the config file is actually applied. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI will validate — this is a workflow-only change. The fix is self-verifying: if the config is applied correctly, MD013 violations from existing files (e.g., `SECURITY.md`, `test/e2e/README.md`) will stop appearing. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- .github/workflows/markdownlint.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/markdownlint.yaml b/.github/workflows/markdownlint.yaml index cb383f3dd2..1fb9fcca1d 100644 --- a/.github/workflows/markdownlint.yaml +++ b/.github/workflows/markdownlint.yaml @@ -20,7 +20,5 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: DavidAnson/markdownlint-cli2-action@07035fd053f7be764496c0f8d8f9f41f98305101 # v22.0.0 with: - command: config - globs: | - .github/.markdownlint.json - **/*.md + config: .github/.markdownlint.json + globs: '**/*.md' From 04dbcd48b6965ee51187c198b3f4217ea0c4350c Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:32:31 +0000 Subject: [PATCH 219/448] chore: Disable MD058, MD059, and MD060 markdown linting rules (#2078) ## Description This PR updates the markdown linter configuration to disable the following rules: - **MD058**: Omit break at the end of a block. - **MD059**: Omit break inside a block. - **MD060**: Omit break after a header. These changes reduce noise in the linting process for existing documentation. ## Related Issue - See CI job failure: https://github.com/microsoft/retina/actions/runs/22402204231/job/64851720792?pr=1981 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/.markdownlint.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/.markdownlint.json b/.github/.markdownlint.json index e0d691f1ee..8693de0cdf 100644 --- a/.github/.markdownlint.json +++ b/.github/.markdownlint.json @@ -2,6 +2,9 @@ "MD013": false, "MD010": false, "MD033": false, + "MD058": false, + "MD059": false, + "MD060": false, "MD024": { "siblings_only": true } From 927be7b2fb33d0737c3a718b7472d11372431aaa Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Wed, 25 Feb 2026 15:45:55 +0000 Subject: [PATCH 220/448] feat(cli): Add `kubectl retina bpftrace` command for real-time network issue tracing (#2061) # Description ## Summary New `bpftrace` subcommand for real-time tracing of network issues on Kubernetes nodes using eBPF/bpftrace. ## Use Cases - Debug packet drops on a node (e.g., NetworkPolicy blocks, routing issues) - Trace TCP connection failures (RST sent/received, connection refused) - Identify retransmissions indicating packet loss or congestion - Filter events by IP or subnet to focus on specific endpoints ```bash # Trace all events (default) kubectl retina bpftrace # Trace only drops and RSTs for a specific IP kubectl retina bpftrace --drops --rst --ip 10.244.1.15 # Trace retransmits for a subnet kubectl retina bpftrace --retransmits --cidr 10.244.0.0/16 ``` ## What's Implemented ### New CLI Command: `kubectl retina bpftrace ` Traces network issues on a specified Kubernetes node with the following capabilities: **Event Types Captured:** | Type | Probe | Description | |------|-------|-------------| | DROP | `kfree_skb` | Packet drops with kernel reason codes (e.g., NETFILTER_DROP for NetworkPolicy) | | RST_SENT | `tcp_send_reset` | TCP RST packets sent by this host | | RST_RECV | `tcp_receive_reset` | TCP RST packets received by this host | | SOCK_ERR | `inet_sk_error_report` | Socket errors (ECONNREFUSED, ETIMEDOUT, etc.) | | RETRANS | `tcp_retransmit_skb` | TCP retransmissions indicating packet loss | ## Flags | Flag | Description | |------|-------------| | `--ip` | Filter by IP address (src or dst) | | `--cidr` | Filter by CIDR (src or dst) | | `--drops` | Enable only packet drop events | | `--rst` | Enable only TCP RST events | | `--errors` | Enable only socket error events | | `--retransmits` | Enable only retransmit events | | `--all` | Enable all events (default) | | `--duration` | Trace duration (0 = until Ctrl-C) | | `--startup-timeout` | Pod startup timeout | | `-o, --output` | Output format: `table` or `json` | When no event flags are specified, all events are traced. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image ## Additional Notes ## Limitations - **IPv4 only**: IPv6 not supported - **Linux only**: Windows nodes not supported - **Cilium CNI**: DROP events won't capture Cilium policy drops (Cilium uses eBPF datapath, not netfilter/kfree_skb) ## Testing ```bash # Build go build -o kubectl-retina ./cli # E2E test (validates all 4 event types) ./test/e2e/test_bpftrace_drops.sh # Manual NODE=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') ./kubectl-retina bpftrace $NODE --duration 30s --retina-shell-image-version v1.0.3 ``` ## Security - IP/CIDR inputs validated and converted to hex (injection-safe) - Commands executed via array-based exec (no shell) - Pod uses minimal capabilities for bpftrace --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos --- cli/README.md | 5 + cli/cmd/bpftrace.go | 350 ++++++++++++++ cli/cmd/bpftrace_test.go | 393 ++++++++++++++++ docs/06-Troubleshooting/bpftrace.md | 169 +++++++ shell/trace.go | 267 +++++++++++ shell/trace_test.go | 383 ++++++++++++++++ shell/tracescript.go | 689 ++++++++++++++++++++++++++++ shell/tracescript_test.go | 635 +++++++++++++++++++++++++ test/e2e/test_bpftrace_drops.sh | 226 +++++++++ test/e2e/test_bpftrace_filter_ip.sh | 317 +++++++++++++ 10 files changed, 3434 insertions(+) create mode 100644 cli/cmd/bpftrace.go create mode 100644 cli/cmd/bpftrace_test.go create mode 100644 docs/06-Troubleshooting/bpftrace.md create mode 100644 shell/trace.go create mode 100644 shell/trace_test.go create mode 100644 shell/tracescript.go create mode 100644 shell/tracescript_test.go create mode 100755 test/e2e/test_bpftrace_drops.sh create mode 100755 test/e2e/test_bpftrace_filter_ip.sh diff --git a/cli/README.md b/cli/README.md index d638fa6ad9..3a2fedb7df 100644 --- a/cli/README.md +++ b/cli/README.md @@ -8,6 +8,11 @@ This directory serves as the entrypoint to Retina CLI Trace subcommand retrieve status or results from Retina. +### bpftrace + +Bpftrace subcommand allows real-time tracing of network issues on Kubernetes nodes using eBPF/bpftrace. +Captures packet drops, TCP RST events, socket errors, and retransmissions. + ### Config Config subcommand configures retina CLI. diff --git a/cli/cmd/bpftrace.go b/cli/cmd/bpftrace.go new file mode 100644 index 0000000000..e59c31d6e6 --- /dev/null +++ b/cli/cmd/bpftrace.go @@ -0,0 +1,350 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package cmd + +import ( + "context" + "errors" + "fmt" + "net" + "os" + "os/signal" + "syscall" + "time" + + "github.com/microsoft/retina/shell" + "github.com/spf13/cobra" + v1 "k8s.io/api/core/v1" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/resource" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/scheme" + "k8s.io/kubectl/pkg/util/templates" +) + +// Trace command flags - use separate variables to avoid conflicts with shell command +var ( + traceConfigFlags *genericclioptions.ConfigFlags + traceMatchVersionFlags *cmdutil.MatchVersionFlags + + // Image settings + traceRetinaShellImageRepo string + traceRetinaShellImageVersion string + + // Filter settings (raw strings from CLI, validated before use) + traceFilterIP string + traceFilterCIDR string + + // Output settings + traceOutputFormat string + traceDuration time.Duration + traceStartupTimeout time.Duration + + // Event selection flags + traceAll bool + traceDrops bool + traceRST bool + traceErrors bool + traceRetransmits bool + traceNfqueueDrops bool +) + +// TraceOutputFormat represents validated output format options +type TraceOutputFormat string + +const ( + TraceOutputTable TraceOutputFormat = "table" + TraceOutputJSON TraceOutputFormat = "json" +) + +// Validation errors +var ( + errInvalidIP = errors.New("invalid IP address") + errIPv6NotSupported = errors.New("IPv6 is not supported, please provide an IPv4 address") + errInvalidCIDR = errors.New("invalid CIDR notation") + errInvalidOutputFormat = errors.New("invalid output format: must be 'table' or 'json'") + errNodeOnly = errors.New("bpftrace command only supports nodes, not pods") +) + +// ValidateFilterIP validates an IP address string and returns the parsed IP. +// Returns nil IP and no error if input is empty (no filter). +// Returns error if input is non-empty but invalid. +func ValidateFilterIP(input string) (net.IP, error) { + if input == "" { + return nil, nil + } + ip := net.ParseIP(input) + if ip == nil { + return nil, fmt.Errorf("%w: %q", errInvalidIP, input) + } + if ip.To4() == nil { + return nil, fmt.Errorf("%w: %q", errIPv6NotSupported, input) + } + return ip, nil +} + +// ValidateFilterCIDR validates a CIDR string and returns the parsed IPNet. +// Returns nil and no error if input is empty (no filter). +// Returns error if input is non-empty but invalid. +func ValidateFilterCIDR(input string) (*net.IPNet, error) { + if input == "" { + return nil, nil + } + _, ipnet, err := net.ParseCIDR(input) + if err != nil { + return nil, fmt.Errorf("%w: %q: %w", errInvalidCIDR, input, err) + } + return ipnet, nil +} + +// ValidateOutputFormat validates the output format string. +func ValidateOutputFormat(input string) (TraceOutputFormat, error) { + switch input { + case "table", "": + return TraceOutputTable, nil + case "json": + return TraceOutputJSON, nil + default: + return "", fmt.Errorf("%w: got %q", errInvalidOutputFormat, input) + } +} + +var bpftraceCmd = &cobra.Command{ + Use: "bpftrace NODE", + Short: "[EXPERIMENTAL] Trace network issues on a node using bpftrace", + Long: templates.LongDesc(` + [EXPERIMENTAL] This is an experimental command. The flags and behavior may change in the future. + + Trace network issues (packet drops, TCP resets, connection errors) on a node in real-time + using bpftrace. + + This creates a privileged pod on the target node that runs bpftrace to capture: + * Packet drops (with drop reason: NETFILTER_DROP, NO_SOCKET, etc.) [--drops] + * TCP RST sent/received (connection refused, reset by peer) [--rst] + * Socket errors (ECONNREFUSED, ETIMEDOUT, etc.) [--errors] + * TCP retransmissions (packet loss indicators) [--retransmits] + * NFQUEUE drops (no consumer on iptables NFQUEUE target) [--nfqueue-drops] + + By default, all event types are traced. Use individual flags to trace specific events only. + + Use --ip or --cidr to focus on specific endpoints. + The filter matches both source AND destination addresses. + + Note: Currently supports IPv4 only. +`), + + Example: templates.Examples(` + # trace all network issues on a node (default) + kubectl retina bpftrace node0001 + + # trace only packet drops + kubectl retina bpftrace node0001 --drops + + # trace drops and RSTs for a specific IP + kubectl retina bpftrace node0001 --drops --rst --ip 10.244.1.15 + + # trace retransmits for a subnet + kubectl retina bpftrace node0001 --retransmits --cidr 10.244.0.0/16 + + # trace for 60 seconds and exit + kubectl retina bpftrace node0001 --duration 60s + + # output in JSON format (for scripting) + kubectl retina bpftrace node0001 --output json + + # trace only socket errors + kubectl retina bpftrace node0001 --errors + + # trace NFQUEUE drops (packets hitting iptables NFQUEUE with no consumer) + kubectl retina bpftrace node0001 --nfqueue-drops + + # combine options + kubectl retina bpftrace node0001 --ip 10.244.1.15 --duration 30s --output json +`), + Args: cobra.ExactArgs(1), + RunE: runBpftrace, +} + +func runBpftrace(_ *cobra.Command, args []string) error { + // Validate image version + if traceRetinaShellImageVersion == "" { + return errMissingRequiredRetinaShellImageVersionArg + } + + // === SECURITY: Validate all user inputs BEFORE any use === + + // Validate IP filter (strict parsing) + filterIP, err := ValidateFilterIP(traceFilterIP) + if err != nil { + return fmt.Errorf("invalid --ip: %w", err) + } + + // Validate CIDR filter (strict parsing) + filterCIDR, err := ValidateFilterCIDR(traceFilterCIDR) + if err != nil { + return fmt.Errorf("invalid --cidr: %w", err) + } + + // Validate output format (whitelist) + outputFormat, err := ValidateOutputFormat(traceOutputFormat) + if err != nil { + return err + } + + // Get namespace + namespace, explicitNamespace, err := traceMatchVersionFlags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return fmt.Errorf("error retrieving namespace arg: %w", err) + } + + // Parse node argument (only nodes supported, not pods) + r := resource.NewBuilder(traceConfigFlags). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). + FilenameParam(explicitNamespace, &resource.FilenameOptions{}). + NamespaceParam(namespace).DefaultNamespace().ResourceNames("nodes", args[0]). + Do() + if rerr := r.Err(); rerr != nil { + return fmt.Errorf("error constructing resource builder: %w", rerr) + } + + // Get REST config + restConfig, err := traceMatchVersionFlags.ToRESTConfig() + if err != nil { + return fmt.Errorf("error constructing REST config: %w", err) + } + + // Visit the resource (should be a node) + return r.Visit(func(info *resource.Info, err error) error { //nolint:wrapcheck // visitor pattern returns errors as-is + if err != nil { + return err + } + + switch obj := info.Object.(type) { + case *v1.Node: + nodeName := obj.Name + podNamespace := namespace + + // Determine which events to trace + // If no individual flags set, or --all is set, enable all events + enableAll := traceAll || (!traceDrops && !traceRST && !traceErrors && !traceRetransmits && !traceNfqueueDrops) + + // Build TraceConfig with validated, typed values only + traceConfig := shell.TraceConfig{ + RestConfig: restConfig, + RetinaShellImage: fmt.Sprintf("%s:%s", traceRetinaShellImageRepo, traceRetinaShellImageVersion), + FilterIPs: nil, + FilterCIDRs: nil, + OutputJSON: outputFormat == TraceOutputJSON, + TraceDuration: traceDuration, + Timeout: traceStartupTimeout, + EnableDrops: enableAll || traceDrops, + EnableRST: enableAll || traceRST, + EnableErrors: enableAll || traceErrors, + EnableRetransmits: enableAll || traceRetransmits, + EnableNfqueueDrops: enableAll || traceNfqueueDrops, + } + + // Add validated IP filter (already typed as net.IP) + if filterIP != nil { + traceConfig.FilterIPs = append(traceConfig.FilterIPs, filterIP) + } + + // Add validated CIDR filter (already typed as *net.IPNet) + if filterCIDR != nil { + traceConfig.FilterCIDRs = append(traceConfig.FilterCIDRs, filterCIDR) + } + + // Create context with cancellation for Ctrl-C handling + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Handle Ctrl-C gracefully + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + defer signal.Stop(sigCh) + go func() { + <-sigCh + fmt.Fprintln(os.Stderr, "\nReceived interrupt, cleaning up...") + cancel() + }() + + // Apply duration timeout if specified + if traceDuration > 0 { + var timeoutCancel context.CancelFunc + ctx, timeoutCancel = context.WithTimeout(ctx, traceDuration) + defer timeoutCancel() + } + + return shell.RunTrace(ctx, traceConfig, nodeName, podNamespace) + + case *v1.Pod: + return errNodeOnly + + default: + gvk := obj.GetObjectKind().GroupVersionKind() + return fmt.Errorf("unsupported resource %s/%s: %w", gvk.GroupVersion(), gvk.Kind, errUnsupportedResourceType) + } + }) +} + +func init() { + Retina.AddCommand(bpftraceCmd) + + bpftraceCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) { + cmd.SilenceUsage = true + cmd.SilenceErrors = true + + // Allow setting image repo and version via environment variables + if !cmd.Flags().Changed("retina-shell-image-repo") { + if envRepo := os.Getenv("RETINA_SHELL_IMAGE_REPO"); envRepo != "" { + traceRetinaShellImageRepo = envRepo + } + } + if !cmd.Flags().Changed("retina-shell-image-version") { + if envVersion := os.Getenv("RETINA_SHELL_IMAGE_VERSION"); envVersion != "" { + traceRetinaShellImageVersion = envVersion + } + } + } + + // Image flags (same as shell command) + bpftraceCmd.Flags().StringVar(&traceRetinaShellImageRepo, "retina-shell-image-repo", + defaultRetinaShellImageRepo, "The container registry repository for the retina-shell image") + bpftraceCmd.Flags().StringVar(&traceRetinaShellImageVersion, "retina-shell-image-version", + defaultRetinaShellImageVersion, "The version (tag) of the retina-shell image") + + // Filter flags + bpftraceCmd.Flags().StringVar(&traceFilterIP, "ip", "", + "Filter by IP address (matches source OR destination)") + bpftraceCmd.Flags().StringVar(&traceFilterCIDR, "cidr", "", + "Filter by CIDR (matches source OR destination)") + + // Event selection flags + bpftraceCmd.Flags().BoolVar(&traceAll, "all", false, + "Enable all event types (default behavior when no event flags specified)") + bpftraceCmd.Flags().BoolVar(&traceDrops, "drops", false, + "Enable packet drop events (kfree_skb tracepoint)") + bpftraceCmd.Flags().BoolVar(&traceRST, "rst", false, + "Enable TCP RST events (tcp_send_reset/tcp_receive_reset)") + bpftraceCmd.Flags().BoolVar(&traceErrors, "errors", false, + "Enable socket error events (inet_sk_error_report)") + bpftraceCmd.Flags().BoolVar(&traceRetransmits, "retransmits", false, + "Enable TCP retransmit events (tcp_retransmit_skb)") + bpftraceCmd.Flags().BoolVar(&traceNfqueueDrops, "nfqueue-drops", false, + "Enable NFQUEUE drop events (fexit:vmlinux:__nf_queue, requires BTF)") + + // Output flags + bpftraceCmd.Flags().StringVarP(&traceOutputFormat, "output", "o", "table", + "Output format: 'table' (human-readable) or 'json' (machine-readable)") + bpftraceCmd.Flags().DurationVar(&traceDuration, "duration", 0, + "How long to trace (e.g., 30s, 5m). 0 means until Ctrl-C.") + bpftraceCmd.Flags().DurationVar(&traceStartupTimeout, "startup-timeout", defaultTimeout, + "Timeout for starting the trace pod") + + // Kubernetes config flags + traceConfigFlags = genericclioptions.NewConfigFlags(true) + traceConfigFlags.AddFlags(bpftraceCmd.PersistentFlags()) + traceMatchVersionFlags = cmdutil.NewMatchVersionFlags(traceConfigFlags) + traceMatchVersionFlags.AddFlags(bpftraceCmd.PersistentFlags()) +} diff --git a/cli/cmd/bpftrace_test.go b/cli/cmd/bpftrace_test.go new file mode 100644 index 0000000000..5bc7558e6a --- /dev/null +++ b/cli/cmd/bpftrace_test.go @@ -0,0 +1,393 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package cmd + +import ( + "net" + "testing" +) + +func TestValidateFilterIP(t *testing.T) { + tests := []struct { + name string + input string + wantIP net.IP + wantErr bool + }{ + // Valid cases + { + name: "valid IPv4", + input: "10.0.0.1", + wantIP: net.ParseIP("10.0.0.1"), + wantErr: false, + }, + { + name: "valid IPv4 192.168", + input: "192.168.1.1", + wantIP: net.ParseIP("192.168.1.1"), + wantErr: false, + }, + { + name: "IPv6 loopback rejected", + input: "::1", + wantIP: nil, + wantErr: true, + }, + { + name: "IPv6 full rejected", + input: "2001:db8::1", + wantIP: nil, + wantErr: true, + }, + { + name: "empty string - no filter", + input: "", + wantIP: nil, + wantErr: false, + }, + // Security: Injection attempts + { + name: "injection attempt - semicolon command", + input: "10.0.0.1; rm -rf /", + wantIP: nil, + wantErr: true, + }, + { + name: "injection attempt - backtick command", + input: "10.0.0.1`whoami`", + wantIP: nil, + wantErr: true, + }, + { + name: "injection attempt - dollar command", + input: "10.0.0.1$(whoami)", + wantIP: nil, + wantErr: true, + }, + { + name: "injection attempt - pipe", + input: "10.0.0.1 | cat /etc/passwd", + wantIP: nil, + wantErr: true, + }, + { + name: "injection attempt - newline", + input: "10.0.0.1\nrm -rf /", + wantIP: nil, + wantErr: true, + }, + // Invalid IPs + { + name: "not an IP - text", + input: "not-an-ip", + wantIP: nil, + wantErr: true, + }, + { + name: "invalid octet - 256", + input: "10.0.0.256", + wantIP: nil, + wantErr: true, + }, + { + name: "invalid format - too many octets", + input: "10.0.0.1.5", + wantIP: nil, + wantErr: true, + }, + { + name: "invalid - CIDR notation", + input: "10.0.0.0/24", + wantIP: nil, + wantErr: true, + }, + { + name: "invalid - hostname", + input: "example.com", + wantIP: nil, + wantErr: true, + }, + { + name: "invalid - negative number", + input: "-1.0.0.1", + wantIP: nil, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotIP, err := ValidateFilterIP(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateFilterIP(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr) + return + } + if tt.wantErr { + return + } + // Compare IPs + if tt.wantIP == nil && gotIP == nil { + return // Both nil, OK + } + if tt.wantIP == nil || gotIP == nil { + t.Errorf("ValidateFilterIP(%q) = %v, want %v", tt.input, gotIP, tt.wantIP) + return + } + if !tt.wantIP.Equal(gotIP) { + t.Errorf("ValidateFilterIP(%q) = %v, want %v", tt.input, gotIP, tt.wantIP) + } + }) + } +} + +func TestValidateFilterCIDR(t *testing.T) { + tests := []struct { + name string + input string + wantCIDR string // Expected CIDR string representation + wantErr bool + }{ + // Valid cases + { + name: "valid /24", + input: "10.0.0.0/24", + wantCIDR: "10.0.0.0/24", + wantErr: false, + }, + { + name: "valid /16", + input: "192.168.0.0/16", + wantCIDR: "192.168.0.0/16", + wantErr: false, + }, + { + name: "valid /8", + input: "10.0.0.0/8", + wantCIDR: "10.0.0.0/8", + wantErr: false, + }, + { + name: "valid /32 single host", + input: "10.0.0.1/32", + wantCIDR: "10.0.0.1/32", + wantErr: false, + }, + { + name: "valid - normalizes to network address", + input: "10.0.0.5/24", + wantCIDR: "10.0.0.0/24", // Normalized + wantErr: false, + }, + { + name: "empty string - no filter", + input: "", + wantCIDR: "", + wantErr: false, + }, + // Security: Injection attempts + { + name: "injection attempt - semicolon", + input: "10.0.0.0/24; rm -rf /", + wantCIDR: "", + wantErr: true, + }, + { + name: "injection attempt - backtick", + input: "10.0.0.0/24`whoami`", + wantCIDR: "", + wantErr: true, + }, + { + name: "injection attempt - newline", + input: "10.0.0.0/24\ncat /etc/passwd", + wantCIDR: "", + wantErr: true, + }, + // Invalid CIDRs + { + name: "invalid - no mask", + input: "10.0.0.0", + wantCIDR: "", + wantErr: true, + }, + { + name: "invalid - mask too large", + input: "10.0.0.0/33", + wantCIDR: "", + wantErr: true, + }, + { + name: "invalid - negative mask", + input: "10.0.0.0/-1", + wantCIDR: "", + wantErr: true, + }, + { + name: "invalid - text", + input: "not-a-cidr", + wantCIDR: "", + wantErr: true, + }, + { + name: "invalid - hostname", + input: "example.com/24", + wantCIDR: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotCIDR, err := ValidateFilterCIDR(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateFilterCIDR(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr) + return + } + if tt.wantErr { + return + } + // Compare CIDRs + if tt.wantCIDR == "" && gotCIDR == nil { + return // Both empty, OK + } + if tt.wantCIDR == "" || gotCIDR == nil { + t.Errorf("ValidateFilterCIDR(%q) = %v, want %v", tt.input, gotCIDR, tt.wantCIDR) + return + } + if gotCIDR.String() != tt.wantCIDR { + t.Errorf("ValidateFilterCIDR(%q) = %v, want %v", tt.input, gotCIDR.String(), tt.wantCIDR) + } + }) + } +} + +func TestValidateOutputFormat(t *testing.T) { + tests := []struct { + name string + input string + wantFormat TraceOutputFormat + wantErr bool + }{ + // Valid cases + { + name: "table", + input: "table", + wantFormat: TraceOutputTable, + wantErr: false, + }, + { + name: "json", + input: "json", + wantFormat: TraceOutputJSON, + wantErr: false, + }, + { + name: "empty defaults to table", + input: "", + wantFormat: TraceOutputTable, + wantErr: false, + }, + // Invalid cases + { + name: "invalid - yaml", + input: "yaml", + wantFormat: "", + wantErr: true, + }, + { + name: "invalid - xml", + input: "xml", + wantFormat: "", + wantErr: true, + }, + { + name: "invalid - random", + input: "notaformat", + wantFormat: "", + wantErr: true, + }, + { + name: "invalid - TABLE uppercase", + input: "TABLE", + wantFormat: "", + wantErr: true, + }, + { + name: "invalid - JSON uppercase", + input: "JSON", + wantFormat: "", + wantErr: true, + }, + // Security: injection attempts + { + name: "injection - semicolon", + input: "table; rm -rf /", + wantFormat: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotFormat, err := ValidateOutputFormat(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateOutputFormat(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr) + return + } + if gotFormat != tt.wantFormat { + t.Errorf("ValidateOutputFormat(%q) = %v, want %v", tt.input, gotFormat, tt.wantFormat) + } + }) + } +} + +// TestValidationRejectsAllInjectionPatterns is a comprehensive security test +// that ensures common injection patterns are rejected by all validators. +func TestValidationRejectsAllInjectionPatterns(t *testing.T) { + injectionPatterns := []string{ + "; rm -rf /", + "| cat /etc/passwd", + "` whoami `", + "`whoami`", + "$(whoami)", + "$((1+1))", + "\n rm -rf /", + "\r\n del *.*", + "&& ls", + "|| ls", + "> /tmp/file", + "< /etc/passwd", + "' OR '1'='1", + "\" OR \"1\"=\"1", + } + + validIP := "10.0.0.1" + validCIDR := "10.0.0.0/24" + + for _, pattern := range injectionPatterns { + t.Run("IP_"+pattern, func(t *testing.T) { + input := validIP + pattern + _, err := ValidateFilterIP(input) + if err == nil { + t.Errorf("ValidateFilterIP(%q) should have returned error for injection pattern", input) + } + }) + + t.Run("CIDR_"+pattern, func(t *testing.T) { + input := validCIDR + pattern + _, err := ValidateFilterCIDR(input) + if err == nil { + t.Errorf("ValidateFilterCIDR(%q) should have returned error for injection pattern", input) + } + }) + + t.Run("Output_"+pattern, func(t *testing.T) { + input := "table" + pattern + _, err := ValidateOutputFormat(input) + if err == nil { + t.Errorf("ValidateOutputFormat(%q) should have returned error for injection pattern", input) + } + }) + } +} diff --git a/docs/06-Troubleshooting/bpftrace.md b/docs/06-Troubleshooting/bpftrace.md new file mode 100644 index 0000000000..7c609613de --- /dev/null +++ b/docs/06-Troubleshooting/bpftrace.md @@ -0,0 +1,169 @@ +# BPF Trace (bpftrace) + +>NOTE: `retina bpftrace` is an experimental feature. The flags and behavior may change in future versions. + +The `retina bpftrace` command allows you to trace network issues on a Kubernetes node in real-time using eBPF/bpftrace. + +This is useful for debugging connectivity problems such as: +- Packet drops (with reason codes) +- TCP RST events (connection resets) +- Socket errors (ECONNREFUSED, ETIMEDOUT, etc.) +- TCP retransmissions (packet loss indicators) + +## Getting Started + +Trace network issues on a node: + +```shell +# Basic usage - trace all network issues on a node +kubectl retina bpftrace + +# With custom duration +kubectl retina bpftrace --duration 60s + +# Filter by IP address +kubectl retina bpftrace --ip 10.224.0.5 + +# Filter by CIDR +kubectl retina bpftrace --cidr 10.224.0.0/16 + +# Output as JSON (for parsing) +kubectl retina bpftrace -o json + +# Trace only specific event types +kubectl retina bpftrace --drops --rst + +# Specify custom timeout for trace pod startup +kubectl retina bpftrace --startup-timeout 120s +``` + +Run `kubectl retina bpftrace -h` for full documentation and examples. + +## Event Types + +The bpftrace command captures several types of network events: + +### DROP - Packet Drops + +Captures packets dropped by the kernel with reason codes. Common reasons include: + +| Code | Name | Description | +|------|------|-------------| +| 0 | NOT_SPECIFIED | Unspecified reason | +| 1 | NO_SOCKET | No listening socket | +| 3 | TCP_CSUM | TCP checksum error | +| 6 | NETFILTER_DROP | Dropped by NetworkPolicy/iptables | +| 8 | IP_CSUM | IP checksum error | + +The full list of drop reasons is kernel-version specific and is printed at the start of each trace. + +### RST_SENT / RST_RECV - TCP Reset Events + +Captures TCP RST packets sent or received. These indicate: +- Connection refused (no service listening) +- Connection reset by peer +- Firewall rejecting connections + +### SOCK_ERR - Socket Errors + +Captures socket-level errors reported to applications: + +| Code | Name | Description | +|------|------|-------------| +| 104 | ECONNRESET | Connection reset by peer | +| 110 | ETIMEDOUT | Connection timed out | +| 111 | ECONNREFUSED | Connection refused | +| 113 | EHOSTUNREACH | No route to host | + +### RETRANS - TCP Retransmissions + +Captures TCP segment retransmissions, which indicate: +- Packet loss in the network +- Network congestion +- Slow or unresponsive peers + +The reason code shows the TCP state during retransmission. + +## Output Format + +### Table Format (default) + +```text +TIME TYPE REASON PROBE SRC -> DST +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── +18:28:12 SOCK_ERR ECONNREFUSED inet_sk_error_report 127.0.0.1:35779 -> 127.0.0.1:9999 +18:28:27 DROP 6 kfree_skb 10.224.0.60:41929 -> 10.224.0.39:80 +18:28:28 RETRANS 2 tcp_retransmit_skb 10.224.0.60:41929 -> 10.224.0.39:80 +18:28:33 RST_SENT - tcp_send_reset 10.224.0.47:38470 -> 20.161.216.95:443 +``` + +### JSON Format (`-o json`) + +```json +{"time":"18:28:12","type":"SOCK_ERR","reason_code":111,"probe":"inet_sk_error_report","src_ip":"127.0.0.1","src_port":35779,"dst_ip":"127.0.0.1","dst_port":9999} +{"time":"18:28:27","type":"DROP","reason_code":6,"probe":"kfree_skb","src_ip":"10.224.0.60","src_port":41929,"dst_ip":"10.224.0.39","dst_port":80} +``` + +## Flags + +| Flag | Type | Default | Description | +|------|------|---------|-------------| +| `--duration` | duration | 0 | Duration to run the trace (0 = until Ctrl-C) | +| `--startup-timeout` | duration | 30s | Timeout for trace pod startup | +| `--ip` | string | "" | Filter events by IP address (matches src or dst) | +| `--cidr` | string | "" | Filter events by CIDR (matches src or dst) | +| `--drops` | bool | false | Enable only packet drop events | +| `--rst` | bool | false | Enable only TCP RST events | +| `--errors` | bool | false | Enable only socket error events | +| `--retransmits` | bool | false | Enable only retransmit events | +| `--all` | bool | false | Enable all event types (default when no event flags specified) | +| `-o, --output` | string | table | Output format: table or json | +| `--retina-shell-image-repo` | string | (default) | Override the retina-shell image repository | +| `--retina-shell-image-version` | string | (default) | Override the retina-shell image version | + +## Example: Debugging NetworkPolicy Drops + +When pods can't communicate due to NetworkPolicy: + +```shell +# Start tracing on the node where the destination pod runs +kubectl retina bpftrace aks-nodepool1-12345678-vmss000000 --drops --duration 60s + +# In another terminal, attempt the connection +kubectl exec -it client-pod -- curl http://server-service:80 +``` + +You'll see output like: + +```text +18:14:41 DROP 6 kfree_skb 10.224.0.34:33061 -> 10.224.0.49:80 +18:14:42 RETRANS 2 tcp_retransmit_skb 10.224.0.34:33061 -> 10.224.0.49:80 +18:14:42 DROP 6 kfree_skb 10.224.0.34:33061 -> 10.224.0.49:80 +``` + +The `DROP` with reason code `6` (NETFILTER_DROP) confirms NetworkPolicy is blocking traffic. + +## Example: Debugging Connection Refused + +When connecting to a service that's not listening: + +```shell +kubectl retina bpftrace node-name --rst --errors --ip 10.224.0.5 +``` + +```text +18:19:05 RST_RECV - tcp_receive_reset 10.224.0.10:35267 -> 10.224.0.5:8080 +18:19:05 SOCK_ERR ECONNREFUSED inet_sk_error_report 10.224.0.10:35267 -> 10.224.0.5:8080 +``` + +This shows the TCP RST and corresponding socket error, indicating no service is listening on port 8080. + +## Requirements + +- Linux nodes (Windows not supported) +- Kernel with BTF support (5.x+ recommended) + +## Limitations + +- IPv6 filtering not currently supported +- Cilium CNI: DROP events won't capture Cilium policy drops (Cilium uses eBPF datapath, not netfilter/kfree_skb) diff --git a/shell/trace.go b/shell/trace.go new file mode 100644 index 0000000000..dea6015c74 --- /dev/null +++ b/shell/trace.go @@ -0,0 +1,267 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package shell + +import ( + "context" + "fmt" + "io" + "net" + "os" + "time" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilrand "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/remotecommand" +) + +// TraceConfig holds the validated configuration for network tracing. +// All fields are typed values - no raw user strings for security. +type TraceConfig struct { + // Kubernetes configuration + RestConfig *rest.Config + RetinaShellImage string + + // Filter configuration (validated, typed values only) + FilterIPs []net.IP // Validated IP addresses to filter + FilterCIDRs []*net.IPNet // Validated CIDRs to filter + + // Output configuration + OutputJSON bool // true for JSON output, false for table + + // Event selection - which probes to enable + EnableDrops bool // Enable packet drop tracing (kfree_skb) + EnableRST bool // Enable TCP RST tracing (tcp_send_reset/tcp_receive_reset) + EnableErrors bool // Enable socket error tracing (inet_sk_error_report) + EnableRetransmits bool // Enable TCP retransmit tracing (tcp_retransmit_skb) + EnableNfqueueDrops bool // Enable NFQUEUE drop tracing (fexit:vmlinux:__nf_queue) + + // Timing configuration + TraceDuration time.Duration // How long to trace (0 = until Ctrl-C) + Timeout time.Duration // Pod startup timeout +} + +// TraceCapabilities returns the required Linux capabilities for bpftrace. +// These are set automatically and not user-configurable. +func TraceCapabilities() []string { + return []string{ + "SYS_ADMIN", // Required for bpftrace + "BPF", // Load BPF programs + "PERFMON", // Perf events access + "NET_ADMIN", // Network tracing + "SYS_PTRACE", // Process tracing (for stack traces) + "SYS_RESOURCE", // Increase rlimits for BPF maps + "MKNOD", // Required for bpftrace debugfs access + "SYS_CHROOT", // Required for bpftrace + } +} + +// RunTrace starts a network trace on a node. +// It creates a privileged pod on the target node, runs bpftrace, and streams output. +func RunTrace(ctx context.Context, config TraceConfig, nodeName, debugPodNamespace string) error { + clientset, err := kubernetes.NewForConfig(config.RestConfig) + if err != nil { + return fmt.Errorf("error constructing kube clientset: %w", err) + } + + // Validate node OS + err = validateOperatingSystemSupportedForNode(ctx, clientset, nodeName) + if err != nil { + return fmt.Errorf("error validating operating system for node %s: %w", nodeName, err) + } + + // Create the trace pod + pod := hostNetworkPodForTrace(config, debugPodNamespace, nodeName) + + fmt.Printf("Creating trace pod %s/%s on node %s\n", debugPodNamespace, pod.Name, nodeName) + createdPod, err := clientset.CoreV1(). + Pods(debugPodNamespace). + Create(ctx, pod, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("error creating trace pod %s in namespace %s: %w", pod.Name, debugPodNamespace, err) + } + + // Ensure cleanup on exit (Ctrl-C, error, or normal termination) + // Note: intentionally using context.Background() for cleanup so it runs even if ctx is canceled + defer func() { //nolint:contextcheck // cleanup must run regardless of parent context state + fmt.Printf("Cleaning up trace pod %s/%s\n", debugPodNamespace, createdPod.Name) + deleteCtx := context.Background() // Use fresh context for cleanup + deleteErr := clientset.CoreV1(). + Pods(debugPodNamespace). + Delete(deleteCtx, createdPod.Name, metav1.DeleteOptions{}) + if deleteErr != nil { + fmt.Fprintf(os.Stderr, "warning: failed to delete trace pod %s: %v\n", createdPod.Name, deleteErr) + } + }() + + // Wait for pod to be running + err = waitForContainerRunning(ctx, config.Timeout, clientset, debugPodNamespace, createdPod.Name, createdPod.Spec.Containers[0].Name) + if err != nil { + return fmt.Errorf("error waiting for trace pod to start: %w", err) + } + + fmt.Printf("Trace pod ready, starting trace...\n") + + // First, fetch and display reason/state codes from kernel + // These are kernel-version specific so we read them at runtime + fmt.Printf("\n") + + // Display SKB drop reason codes (for DROP events) + dropReasonsCommand := DropReasonsCommand() + err = execInPod(ctx, config.RestConfig, clientset, debugPodNamespace, createdPod.Name, createdPod.Spec.Containers[0].Name, dropReasonsCommand, os.Stdout, os.Stderr) + if err != nil { + // Non-fatal: continue even if we can't get reason codes + fmt.Fprintf(os.Stderr, "warning: could not fetch drop reason codes: %v\n", err) + } + fmt.Printf("\n") + + // Generate and run the bpftrace script + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Run bpftrace with the generated script + // SECURITY: The script is passed via -e flag, not interpolated into a shell command + bpftraceCommand := []string{"bpftrace", "-e", script} + + err = execInPod(ctx, config.RestConfig, clientset, debugPodNamespace, createdPod.Name, createdPod.Spec.Containers[0].Name, bpftraceCommand, os.Stdout, os.Stderr) + if err != nil { + // If duration was specified and context was cancelled, it's expected behavior + if config.TraceDuration > 0 && ctx.Err() != nil { + fmt.Printf("\nTrace completed after %s\n", config.TraceDuration) + return nil + } + return fmt.Errorf("error executing trace command: %w", err) + } + + return nil +} + +// execInPod executes a command inside a pod container without using a shell. +// SECURITY: The command is passed as an array directly to the container runtime, +// preventing shell injection attacks. No shell interpolation occurs. +// +// Parameters: +// - ctx: Context for cancellation (e.g., Ctrl-C) +// - restConfig: Kubernetes REST client config +// - clientset: Kubernetes clientset +// - namespace: Pod namespace +// - podName: Pod name +// - containerName: Container name +// - command: Command and arguments as string array (NO SHELL - passed directly) +// - stdout: Writer for stdout (typically os.Stdout) +// - stderr: Writer for stderr (typically os.Stderr) +func execInPod( + ctx context.Context, + restConfig *rest.Config, + clientset *kubernetes.Clientset, + namespace, podName, containerName string, + command []string, + stdout, stderr io.Writer, +) error { + // Build the exec request using the REST API directly + // SECURITY: Command is passed as array in PodExecOptions, NOT through a shell + req := clientset.CoreV1().RESTClient(). + Post(). + Resource("pods"). + Name(podName). + Namespace(namespace). + SubResource("exec"). + VersionedParams(&v1.PodExecOptions{ + Container: containerName, + Command: command, // Direct command array - no shell! + Stdin: false, + Stdout: true, + Stderr: true, + TTY: false, + }, scheme.ParameterCodec) + + // Create the SPDY executor + exec, err := remotecommand.NewSPDYExecutor(restConfig, "POST", req.URL()) + if err != nil { + return fmt.Errorf("error creating executor: %w", err) + } + + // Stream the output + // The Stream function blocks until the command completes or context is cancelled + err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{ + Stdout: stdout, + Stderr: stderr, + }) + if err != nil { + // Check if it was a context cancellation (user pressed Ctrl-C) + if ctx.Err() != nil { + return fmt.Errorf("context error: %w", ctx.Err()) + } + return fmt.Errorf("error streaming command output: %w", err) + } + + return nil +} + +// hostNetworkPodForTrace creates a pod manifest for network tracing. +// The pod runs with host network and required capabilities for bpftrace. +func hostNetworkPodForTrace(config TraceConfig, debugPodNamespace, nodeName string) *v1.Pod { + // Use Args (not Command) to preserve the image entrypoint. + // The entrypoint.sh in retina-shell image mounts debugfs/tracefs which bpftrace needs. + args := []string{"sleep", "infinity"} + + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: randomTraceContainerName(), + Namespace: debugPodNamespace, + Labels: map[string]string{ + "app": "retina-trace", + "retina.sh/component": "trace", + "retina.sh/trace-target-node": nodeName, + }, + }, + Spec: v1.PodSpec{ + NodeName: nodeName, + RestartPolicy: v1.RestartPolicyNever, + Tolerations: []v1.Toleration{{Operator: v1.TolerationOpExists}}, + HostNetwork: true, + HostPID: true, // Required for full process visibility + Containers: []v1.Container{ + { + Name: "retina-trace", + Image: config.RetinaShellImage, + Args: args, // Use Args to preserve entrypoint.sh + Stdin: false, // Not interactive + TTY: false, // Not interactive + SecurityContext: &v1.SecurityContext{ + Privileged: boolPtr(false), // Use capabilities instead + Capabilities: &v1.Capabilities{ + Drop: []v1.Capability{"ALL"}, + Add: stringSliceToCapabilities(TraceCapabilities()), + }, + // Required for bpftrace (per shell.md documentation) + SeccompProfile: &v1.SeccompProfile{ + Type: v1.SeccompProfileTypeUnconfined, + }, + AppArmorProfile: &v1.AppArmorProfile{ + Type: v1.AppArmorProfileTypeUnconfined, + }, + }, + }, + }, + }, + } + + return pod +} + +// randomTraceContainerName generates a unique name for the trace pod. +func randomTraceContainerName() string { + const randLen = 5 + return "retina-trace-" + utilrand.String(randLen) +} + +// boolPtr returns a pointer to a bool value. +func boolPtr(b bool) *bool { + return &b +} diff --git a/shell/trace_test.go b/shell/trace_test.go new file mode 100644 index 0000000000..59f8d444dc --- /dev/null +++ b/shell/trace_test.go @@ -0,0 +1,383 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package shell + +import ( + "bytes" + "context" + "errors" + "net" + "strings" + "testing" + "time" + + v1 "k8s.io/api/core/v1" +) + +func TestTraceCapabilities(t *testing.T) { + caps := TraceCapabilities() + + // Must have at least these required capabilities for bpftrace + requiredCaps := []string{ + "SYS_ADMIN", + "BPF", + "PERFMON", + "NET_ADMIN", + } + + capSet := make(map[string]bool) + for _, c := range caps { + capSet[c] = true + } + + for _, required := range requiredCaps { + if !capSet[required] { + t.Errorf("TraceCapabilities() missing required capability: %s", required) + } + } +} + +func TestTraceConfigTypedFields(t *testing.T) { + // Verify TraceConfig only accepts typed values, not raw strings + config := TraceConfig{ + FilterIPs: []net.IP{net.ParseIP("10.0.0.1")}, + FilterCIDRs: []*net.IPNet{}, + OutputJSON: true, + } + + // FilterIPs should be net.IP, not string + if len(config.FilterIPs) != 1 { + t.Errorf("Expected 1 FilterIP, got %d", len(config.FilterIPs)) + } + if !config.FilterIPs[0].Equal(net.ParseIP("10.0.0.1")) { + t.Errorf("FilterIP not set correctly") + } + + // Verify OutputJSON is bool, not string + if !config.OutputJSON { + t.Errorf("OutputJSON should be true") + } +} + +func TestHostNetworkPodForTrace(t *testing.T) { + config := TraceConfig{ + RetinaShellImage: "mcr.microsoft.com/containernetworking/retina-shell:v1.0.0", + } + + pod := hostNetworkPodForTrace(config, "kube-system", "node-001") + + // Test basic pod properties + t.Run("namespace", func(t *testing.T) { + if pod.Namespace != "kube-system" { + t.Errorf("Expected namespace kube-system, got %s", pod.Namespace) + } + }) + + t.Run("node selector", func(t *testing.T) { + if pod.Spec.NodeName != "node-001" { + t.Errorf("Expected nodeName node-001, got %s", pod.Spec.NodeName) + } + }) + + t.Run("host network enabled", func(t *testing.T) { + if !pod.Spec.HostNetwork { + t.Error("Expected HostNetwork to be true") + } + }) + + t.Run("host PID enabled", func(t *testing.T) { + if !pod.Spec.HostPID { + t.Error("Expected HostPID to be true for bpftrace") + } + }) + + t.Run("tolerates all taints", func(t *testing.T) { + found := false + for _, tol := range pod.Spec.Tolerations { + if tol.Operator == v1.TolerationOpExists { + found = true + break + } + } + if !found { + t.Error("Expected toleration with Operator=Exists to run on any node") + } + }) + + t.Run("restart policy never", func(t *testing.T) { + if pod.Spec.RestartPolicy != v1.RestartPolicyNever { + t.Errorf("Expected RestartPolicy Never, got %s", pod.Spec.RestartPolicy) + } + }) + + t.Run("image set correctly", func(t *testing.T) { + if len(pod.Spec.Containers) != 1 { + t.Fatalf("Expected 1 container, got %d", len(pod.Spec.Containers)) + } + if pod.Spec.Containers[0].Image != config.RetinaShellImage { + t.Errorf("Expected image %s, got %s", config.RetinaShellImage, pod.Spec.Containers[0].Image) + } + }) + + t.Run("not interactive", func(t *testing.T) { + container := pod.Spec.Containers[0] + if container.Stdin { + t.Error("Expected Stdin to be false for non-interactive trace") + } + if container.TTY { + t.Error("Expected TTY to be false for non-interactive trace") + } + }) + + t.Run("has trace labels", func(t *testing.T) { + if pod.Labels["app"] != "retina-trace" { + t.Errorf("Expected label app=retina-trace, got %s", pod.Labels["app"]) + } + if pod.Labels["retina.sh/trace-target-node"] != "node-001" { + t.Errorf("Expected node label, got %s", pod.Labels["retina.sh/trace-target-node"]) + } + }) +} + +func TestHostNetworkPodForTraceSecurityContext(t *testing.T) { + config := TraceConfig{ + RetinaShellImage: "test-image:v1", + } + + pod := hostNetworkPodForTrace(config, "default", "test-node") + container := pod.Spec.Containers[0] + secCtx := container.SecurityContext + + t.Run("not privileged", func(t *testing.T) { + if secCtx.Privileged != nil && *secCtx.Privileged { + t.Error("Pod should use capabilities, not privileged mode") + } + }) + + t.Run("drops all capabilities", func(t *testing.T) { + if secCtx.Capabilities == nil { + t.Fatal("Expected Capabilities to be set") + } + + foundDropAll := false + for _, drop := range secCtx.Capabilities.Drop { + if string(drop) == "ALL" { + foundDropAll = true + break + } + } + if !foundDropAll { + t.Error("Expected to drop ALL capabilities first") + } + }) + + t.Run("adds required capabilities", func(t *testing.T) { + if secCtx.Capabilities == nil { + t.Fatal("Expected Capabilities to be set") + } + + addedCaps := make(map[string]bool) + for _, cap := range secCtx.Capabilities.Add { + addedCaps[string(cap)] = true + } + + requiredCaps := TraceCapabilities() + for _, required := range requiredCaps { + if !addedCaps[required] { + t.Errorf("Missing required capability: %s", required) + } + } + }) + + t.Run("seccomp unconfined", func(t *testing.T) { + if secCtx.SeccompProfile == nil { + t.Fatal("Expected SeccompProfile to be set") + } + if secCtx.SeccompProfile.Type != v1.SeccompProfileTypeUnconfined { + t.Errorf("Expected Seccomp Unconfined, got %s", secCtx.SeccompProfile.Type) + } + }) +} + +func TestRandomTraceContainerName(t *testing.T) { + name1 := randomTraceContainerName() + name2 := randomTraceContainerName() + + t.Run("has prefix", func(t *testing.T) { + if len(name1) < 14 || name1[:13] != "retina-trace-" { + t.Errorf("Expected prefix 'retina-trace-', got %s", name1) + } + }) + + t.Run("unique names", func(t *testing.T) { + if name1 == name2 { + t.Errorf("Expected unique names, got %s and %s", name1, name2) + } + }) +} + +func TestBoolPtr(t *testing.T) { + truePtr := boolPtr(true) + falsePtr := boolPtr(false) + + if truePtr == nil || *truePtr != true { + t.Error("boolPtr(true) should return pointer to true") + } + if falsePtr == nil || *falsePtr != false { + t.Error("boolPtr(false) should return pointer to false") + } +} + +// TestExecInPodCommandIsArray verifies that execInPod takes command as array +// This is a security test - commands must NOT be passed through a shell +func TestExecInPodCommandIsArray(t *testing.T) { + // This test verifies the function signature and documentation + // The actual exec requires a running cluster, but we can verify + // that the function is designed correctly + + // Verify the function signature accepts []string for command + // If this compiles, the function correctly uses array, not string + commandArray := []string{"bpftrace", "-e", "tracepoint:skb:kfree_skb { }"} + + // Ensure the command array contains separate elements + if len(commandArray) != 3 { + t.Errorf("Command should be array of 3 elements, got %d", len(commandArray)) + } + + // Verify no shell metacharacters would be interpreted + // (they're just strings in an array, not executed by shell) + dangerousInput := "test; rm -rf /" + testCommand := []string{"echo", dangerousInput} + + // In a shell: echo "test; rm -rf /" would be safe + // But echo test; rm -rf / would be dangerous + // With array exec: ["echo", "test; rm -rf /"] is always safe + // because "test; rm -rf /" is passed as a single argument to echo + + if testCommand[0] != "echo" { + t.Error("First element should be 'echo'") + } + if testCommand[1] != dangerousInput { + t.Error("Second element should be the dangerous input as-is (not interpreted)") + } + + // The key security property: the dangerous input stays as ONE argument + // It's not split by shell + if len(testCommand) != 2 { + t.Errorf("Command should have exactly 2 elements (not shell-split), got %d", len(testCommand)) + } +} + +// TestExecInPodContextCancellation verifies context cancellation behavior +func TestExecInPodContextCancellation(t *testing.T) { + // Create a cancelled context + ctx, cancel := context.WithCancel(context.Background()) + cancel() // Cancel immediately + + // Verify context is done + select { + case <-ctx.Done(): + // Expected - context should be cancelled + if !errors.Is(ctx.Err(), context.Canceled) { + t.Errorf("Expected context.Canceled, got %v", ctx.Err()) + } + default: + t.Error("Context should be done after cancel()") + } +} + +// TestExecInPodTimeoutContext verifies timeout context behavior +func TestExecInPodTimeoutContext(t *testing.T) { + // Create a context with very short timeout + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond) + defer cancel() + + // Wait for timeout + time.Sleep(5 * time.Millisecond) + + // Verify context is done due to deadline + select { + case <-ctx.Done(): + if !errors.Is(ctx.Err(), context.DeadlineExceeded) { + t.Errorf("Expected context.DeadlineExceeded, got %v", ctx.Err()) + } + default: + t.Error("Context should be done after timeout") + } +} + +// TestExecOutputWriters verifies stdout/stderr writers work correctly +func TestExecOutputWriters(t *testing.T) { + // This tests that our output handling pattern works correctly + var stdout, stderr bytes.Buffer + + // Simulate writing to both + stdout.WriteString("stdout output\n") + stderr.WriteString("stderr output\n") + + if !strings.Contains(stdout.String(), "stdout") { + t.Error("stdout buffer should contain stdout output") + } + if !strings.Contains(stderr.String(), "stderr") { + t.Error("stderr buffer should contain stderr output") + } +} + +// TestExecCommandNoShellInterpolation verifies that special characters +// are NOT interpreted when passed in command array +func TestExecCommandNoShellInterpolation(t *testing.T) { + // These strings would be dangerous if passed to a shell + // But in array form, they're just literal strings + testCases := []struct { + name string + command []string + }{ + { + name: "semicolon injection", + command: []string{"echo", "safe; rm -rf /"}, + }, + { + name: "backtick injection", + command: []string{"echo", "`whoami`"}, + }, + { + name: "dollar injection", + command: []string{"echo", "$(id)"}, + }, + { + name: "pipe injection", + command: []string{"echo", "data | cat /etc/passwd"}, + }, + { + name: "redirect injection", + command: []string{"echo", "> /tmp/evil"}, + }, + { + name: "newline injection", + command: []string{"echo", "line1\nrm -rf /"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // In proper array exec, the "dangerous" part is always + // the second element - it's never parsed or split + if len(tc.command) != 2 { + t.Errorf("Expected 2-element array, got %d", len(tc.command)) + } + if tc.command[0] != "echo" { + t.Error("First element should be 'echo'") + } + // The second element contains the "dangerous" string + // but it's just a literal string, not executed + if tc.command[1] == "" { + t.Error("Second element should not be empty") + } + + // Key assertion: the command array length proves no shell parsing + // Shell would split "echo safe; rm -rf /" into multiple commands + // Array exec keeps it as ["echo", "safe; rm -rf /"] = 2 elements + }) + } +} diff --git a/shell/tracescript.go b/shell/tracescript.go new file mode 100644 index 0000000000..37332077a5 --- /dev/null +++ b/shell/tracescript.go @@ -0,0 +1,689 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package shell + +import ( + "encoding/binary" + "fmt" + "net" + "strings" +) + +// ScriptGenerator generates bpftrace scripts for network tracing. +// SECURITY: All IP addresses are converted to hex representation to prevent injection. +type ScriptGenerator struct { + config TraceConfig +} + +// NewScriptGenerator creates a new script generator with the given config. +func NewScriptGenerator(config TraceConfig) *ScriptGenerator { + return &ScriptGenerator{config: config} +} + +// Generate creates the complete bpftrace script. +func (g *ScriptGenerator) Generate() string { + var sb strings.Builder + + // Write script header + sb.WriteString(g.generateHeader()) + + // Write BEGIN block + sb.WriteString(g.generateBeginBlock()) + + // Conditionally write probes based on config + if g.config.EnableDrops { + sb.WriteString(g.generateDropTracepoint()) + } + + if g.config.EnableRST { + sb.WriteString(g.generateRSTTracepoints()) + } + + if g.config.EnableErrors { + sb.WriteString(g.generateSocketErrorTracepoint()) + } + + if g.config.EnableRetransmits { + sb.WriteString(g.generateRetransmitTracepoint()) + } + + if g.config.EnableNfqueueDrops { + sb.WriteString(g.generateNfqueueDropProbe()) + } + + // Write END block + sb.WriteString(g.generateEndBlock()) + + return sb.String() +} + +// generateHeader creates the script header with comments. +// Note: No #include directives - bpftrace uses BTF for struct access. +func (g *ScriptGenerator) generateHeader() string { + return `#!/usr/bin/env bpftrace +/* + * Network Issue Tracer - Generated by retina bpftrace + * Traces: + * - Packet drops with reason codes + * - TCP RST sent/received (connection failures) + * + * Note: Uses BTF for struct access (no kernel headers needed) + */ + +` +} + +// generateBeginBlock creates the BEGIN block with initialization. +func (g *ScriptGenerator) generateBeginBlock() string { + var sb strings.Builder + + sb.WriteString("BEGIN {\n") + + if g.config.OutputJSON { + sb.WriteString(` printf("{\"event\":\"start\",\"message\":\"Tracing network issues...\"}\n");`) + } else { + sb.WriteString(` printf("Tracing network issues... Press Ctrl-C to stop.\n\n");`) + sb.WriteString("\n") + sb.WriteString(` printf("%-12s %-10s %-18s %-18s %-18s %s\n",`) + sb.WriteString("\n") + sb.WriteString(` "TIME", "TYPE", "REASON", "STATE", "PROBE", "SRC -> DST");`) + sb.WriteString("\n") + sb.WriteString(` printf("────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n");`) + } + + sb.WriteString("\n}\n\n") + return sb.String() +} + +// generateDropTracepoint creates the kfree_skb tracepoint for packet drops. +func (g *ScriptGenerator) generateDropTracepoint() string { + var sb strings.Builder + + // Tracepoint for packet drops + // Note: No pre-filter here because we need to parse skb to get IPs. + // IP filtering is done in the body after extracting addresses. + sb.WriteString("tracepoint:skb:kfree_skb\n") + sb.WriteString("{\n") + + // Extract packet info + sb.WriteString(` $skb = (struct sk_buff *)args->skbaddr; + $reason = args->reason; + + // Skip non-drop events (reason 0-2 are not real drops) + if ($reason <= 2) { return; } + + $protocol = $skb->protocol; + + // Only process IPv4 for now + if (bswap($protocol) != 0x0800) { return; } + + $iph = (struct iphdr *)($skb->head + $skb->network_header); + $saddr_raw = $iph->saddr; + $daddr_raw = $iph->daddr; + $saddr = ntop(2, $saddr_raw); + $daddr = ntop(2, $daddr_raw); + $ipproto = $iph->protocol; + +`) + + // Add IP/CIDR filter inside the body if specified + ipFilter := g.buildSkbIPFilterCondition() + if ipFilter != "" { + sb.WriteString(ipFilter) + } + + sb.WriteString(` $sport = (uint16)0; + $dport = (uint16)0; + + // Extract ports for TCP/UDP + if ($ipproto == 6 || $ipproto == 17) { + $transport_off = $skb->transport_header; + if ($transport_off > 0 && $transport_off < 65535) { + $th = $skb->head + $transport_off; + $sport = bswap(*(uint16*)($th)); + $dport = bswap(*(uint16*)($th + 2)); + } + } + +`) + + // Generate output based on format + if g.config.OutputJSON { + sb.WriteString(g.generateJSONOutput()) + } else { + sb.WriteString(g.generateTableOutput()) + } + + sb.WriteString("}\n\n") + return sb.String() +} + +// generateRSTTracepoints creates tracepoints for TCP RST events. +func (g *ScriptGenerator) generateRSTTracepoints() string { + var sb strings.Builder + + // TCP RST sent - when this host sends a RST + sb.WriteString(g.generateRSTSentTracepoint()) + + // TCP RST received - when this host receives a RST + sb.WriteString(g.generateRSTReceivedTracepoint()) + + return sb.String() +} + +// generateRSTSentTracepoint creates the tcp_send_reset tracepoint. +func (g *ScriptGenerator) generateRSTSentTracepoint() string { + var sb strings.Builder + + sb.WriteString("tracepoint:tcp:tcp_send_reset\n") + sb.WriteString("{\n") + + // Only process IPv4 (family == 2) + sb.WriteString(` if (args->family != 2) { return; } + +`) + + // Extract bytes into local vars first (required for BPF verifier) + if g.hasIPFilter() { + sb.WriteString(` // Read IP bytes into local vars for filtering + $s0 = args->saddr[0]; $s1 = args->saddr[1]; $s2 = args->saddr[2]; $s3 = args->saddr[3]; + $d0 = args->daddr[0]; $d1 = args->daddr[1]; $d2 = args->daddr[2]; $d3 = args->daddr[3]; + +`) + // Add IP filter using local vars + sb.WriteString(g.buildTCPIPFilterCheckFromLocalVars()) + } + + sb.WriteString(` $saddr = ntop(2, args->saddr); + $daddr = ntop(2, args->daddr); + $sport = args->sport; + $dport = args->dport; + +`) + + if g.config.OutputJSON { + sb.WriteString(` printf("{\"time\":\"%s\",\"type\":\"RST_SENT\",\"probe\":\"tcp_send_reset\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", + strftime("%H:%M:%S", nsecs), + $saddr, $sport, + $daddr, $dport); +`) + } else { + sb.WriteString(` printf("%-12s %-10s %-18s %-18s %-18s %s:%-5d -> %s:%-5d\n", + strftime("%H:%M:%S", nsecs), + "RST_SENT", + "-", + "-", + "tcp_send_reset", + $saddr, $sport, + $daddr, $dport); +`) + } + + sb.WriteString("}\n\n") + return sb.String() +} + +// generateRSTReceivedTracepoint creates the tcp_receive_reset tracepoint. +func (g *ScriptGenerator) generateRSTReceivedTracepoint() string { + var sb strings.Builder + + sb.WriteString("tracepoint:tcp:tcp_receive_reset\n") + sb.WriteString("{\n") + + // Only process IPv4 (family == 2) + sb.WriteString(` if (args->family != 2) { return; } + +`) + + // Extract bytes into local vars first (required for BPF verifier) + if g.hasIPFilter() { + sb.WriteString(` // Read IP bytes into local vars for filtering + $s0 = args->saddr[0]; $s1 = args->saddr[1]; $s2 = args->saddr[2]; $s3 = args->saddr[3]; + $d0 = args->daddr[0]; $d1 = args->daddr[1]; $d2 = args->daddr[2]; $d3 = args->daddr[3]; + +`) + // Add IP filter using local vars + sb.WriteString(g.buildTCPIPFilterCheckFromLocalVars()) + } + + sb.WriteString(` $saddr = ntop(2, args->saddr); + $daddr = ntop(2, args->daddr); + $sport = args->sport; + $dport = args->dport; + +`) + + if g.config.OutputJSON { + sb.WriteString(` printf("{\"time\":\"%s\",\"type\":\"RST_RECV\",\"probe\":\"tcp_receive_reset\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", + strftime("%H:%M:%S", nsecs), + $saddr, $sport, + $daddr, $dport); +`) + } else { + sb.WriteString(` printf("%-12s %-10s %-18s %-18s %-18s %s:%-5d -> %s:%-5d\n", + strftime("%H:%M:%S", nsecs), + "RST_RECV", + "-", + "-", + "tcp_receive_reset", + $saddr, $sport, + $daddr, $dport); +`) + } + + sb.WriteString("}\n\n") + return sb.String() +} + +// generateSocketErrorTracepoint creates the inet_sk_error_report tracepoint. +// This captures socket errors like ECONNREFUSED, ETIMEDOUT, etc. +func (g *ScriptGenerator) generateSocketErrorTracepoint() string { + var sb strings.Builder + + sb.WriteString("tracepoint:sock:inet_sk_error_report\n") + sb.WriteString("{\n") + + // Only process IPv4 (family == 2) and skip error=0 (not a real error) + sb.WriteString(` if (args->family != 2) { return; } + if (args->error == 0) { return; } // Skip non-error events (socket cleanup) + +`) + + // Extract bytes into local vars first (required for BPF verifier) + if g.hasIPFilter() { + sb.WriteString(` // Read IP bytes into local vars for filtering + $s0 = args->saddr[0]; $s1 = args->saddr[1]; $s2 = args->saddr[2]; $s3 = args->saddr[3]; + $d0 = args->daddr[0]; $d1 = args->daddr[1]; $d2 = args->daddr[2]; $d3 = args->daddr[3]; + +`) + // Add IP filter using local vars + sb.WriteString(g.buildTCPIPFilterCheckFromLocalVars()) + } + + sb.WriteString(` $saddr = ntop(2, args->saddr); + $daddr = ntop(2, args->daddr); + $sport = args->sport; + $dport = args->dport; + $error = args->error; + +`) + + if g.config.OutputJSON { + // JSON output: use error code only (parsers can decode POSIX errno) + sb.WriteString(` printf("{\"time\":\"%s\",\"type\":\"SOCK_ERR\",\"errno\":%d,\"probe\":\"inet_sk_error_report\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", + strftime("%H:%M:%S", nsecs), + $error, + $saddr, $sport, + $daddr, $dport); +`) + } else { + // Table output: decode errno to human-readable name + sb.WriteString(` // Decode common socket errno values (POSIX standard) + $errno_name = $error == 104 ? "ECONNRESET" : + $error == 110 ? "ETIMEDOUT" : + $error == 111 ? "ECONNREFUSED" : + $error == 113 ? "EHOSTUNREACH" : + $error == 101 ? "ENETUNREACH" : + $error == 99 ? "EADDRNOTAVAIL" : + $error == 112 ? "EHOSTDOWN" : + $error == 103 ? "ECONNABORTED" : + "UNKNOWN"; + + printf("%-12s %-10s %-18s %-18s %-18s %s:%-5d -> %s:%-5d\n", + strftime("%H:%M:%S", nsecs), + "SOCK_ERR", + $errno_name, + "-", + "inet_sk_error_report", + $saddr, $sport, + $daddr, $dport); +`) + } + + sb.WriteString("}\n\n") + return sb.String() +} + +// generateRetransmitTracepoint creates the tcp_retransmit_skb tracepoint. +// This captures TCP retransmissions which indicate packet loss or congestion. +func (g *ScriptGenerator) generateRetransmitTracepoint() string { + var sb strings.Builder + + sb.WriteString("tracepoint:tcp:tcp_retransmit_skb\n") + sb.WriteString("{\n") + + // Only process IPv4 (family == 2) + sb.WriteString(` if (args->family != 2) { return; } + +`) + + // Extract bytes into local vars first (required for BPF verifier) + if g.hasIPFilter() { + sb.WriteString(` // Read IP bytes into local vars for filtering + $s0 = args->saddr[0]; $s1 = args->saddr[1]; $s2 = args->saddr[2]; $s3 = args->saddr[3]; + $d0 = args->daddr[0]; $d1 = args->daddr[1]; $d2 = args->daddr[2]; $d3 = args->daddr[3]; + +`) + // Add IP filter using local vars + sb.WriteString(g.buildTCPIPFilterCheckFromLocalVars()) + } + + sb.WriteString(` $saddr = ntop(2, args->saddr); + $daddr = ntop(2, args->daddr); + $sport = args->sport; + $dport = args->dport; + $state = args->state; + +`) + + if g.config.OutputJSON { + // JSON: use numeric tcp_state to avoid BPF verifier complexity with string variables + // State values: 1=ESTABLISHED, 2=SYN_SENT, 3=SYN_RECV, 4=FIN_WAIT1, etc. + sb.WriteString(` printf("{\"time\":\"%s\",\"type\":\"RETRANS\",\"tcp_state\":%d,\"probe\":\"tcp_retransmit_skb\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", + strftime("%H:%M:%S", nsecs), + $state, + $saddr, $sport, + $daddr, $dport); +`) + } else { + // Table: decode TCP state to human-readable name (fixed values from include/net/tcp_states.h) + sb.WriteString(` $state_name = $state == 1 ? "ESTABLISHED" : + $state == 2 ? "SYN_SENT" : + $state == 3 ? "SYN_RECV" : + $state == 4 ? "FIN_WAIT1" : + $state == 5 ? "FIN_WAIT2" : + $state == 6 ? "TIME_WAIT" : + $state == 7 ? "CLOSE" : + $state == 8 ? "CLOSE_WAIT" : + $state == 9 ? "LAST_ACK" : + $state == 10 ? "LISTEN" : + $state == 11 ? "CLOSING" : + $state == 12 ? "NEW_SYN_RECV" : + "UNKNOWN"; + + printf("%-12s %-10s %-18s %-18s %-18s %s:%-5d -> %s:%-5d\n", + strftime("%H:%M:%S", nsecs), + "RETRANS", + "-", + $state_name, + "tcp_retransmit_skb", + $saddr, $sport, + $daddr, $dport); +`) + } + + sb.WriteString("}\n\n") + return sb.String() +} + +// generateNfqueueDropProbe creates the fexit probe for NFQUEUE drops. +// Detects packets sent to NFQUEUE when no userspace consumer is bound to the queue. +// Uses fexit:vmlinux:__nf_queue which provides access to both function arguments +// and return value in a single probe. Requires kernel >= 5.5 with BTF support. +// +// __nf_queue returns negative errno on failure: +// +// -ESRCH (-3): no queue handler registered (no consumer on the queue) +// -ENOMEM (-12): failed to allocate queue entry +// -ENETDOWN (-100): network interface down during queue +func (g *ScriptGenerator) generateNfqueueDropProbe() string { + var sb strings.Builder + + sb.WriteString("fexit:vmlinux:__nf_queue\n") + sb.WriteString("{\n") + + // Only report failures (retval < 0 means queue delivery failed) + sb.WriteString(` if (retval >= 0) { return; } + + $skb = args->skb; + + // Only process IPv4 + $protocol = $skb->protocol; + if (bswap($protocol) != 0x0800) { return; } + + $iph = (struct iphdr *)($skb->head + $skb->network_header); + $saddr_raw = $iph->saddr; + $daddr_raw = $iph->daddr; + +`) + + // Add IP/CIDR filter if specified (reuses the same bswap-based filter as kfree_skb) + ipFilter := g.buildSkbIPFilterCondition() + if ipFilter != "" { + sb.WriteString(ipFilter) + } + + sb.WriteString(` $saddr = ntop(2, $saddr_raw); + $daddr = ntop(2, $daddr_raw); + $queuenum = args->queuenum; + $ipproto = $iph->protocol; + + $sport = (uint16)0; + $dport = (uint16)0; + + // Extract ports for TCP/UDP + if ($ipproto == 6 || $ipproto == 17) { + $transport_off = $skb->transport_header; + if ($transport_off > 0 && $transport_off < 65535) { + $th = $skb->head + $transport_off; + $sport = bswap(*(uint16*)($th)); + $dport = bswap(*(uint16*)($th + 2)); + } + } + +`) + + if g.config.OutputJSON { + sb.WriteString(` printf("{\"time\":\"%s\",\"type\":\"NFQ_DROP\",\"queue\":%d,\"errno\":%d,\"probe\":\"__nf_queue\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", + strftime("%H:%M:%S", nsecs), + $queuenum, retval, + $saddr, $sport, + $daddr, $dport); +`) + } else { + sb.WriteString(` // Decode errno to human-readable name + $errno_name = retval == -3 ? "ESRCH" : + retval == -12 ? "ENOMEM" : + retval == -100 ? "ENETDOWN" : + "UNKNOWN"; + + printf("%-12s %-10s %-18s %-18s %-18s %s:%-5d -> %s:%-5d\n", + strftime("%H:%M:%S", nsecs), + "NFQ_DROP", + $errno_name, + "-", + "__nf_queue", + $saddr, $sport, + $daddr, $dport); +`) + } + + sb.WriteString("}\n\n") + return sb.String() +} + +// hasIPFilter returns true if any IP or CIDR filter is configured. +func (g *ScriptGenerator) hasIPFilter() bool { + return len(g.config.FilterIPs) > 0 || len(g.config.FilterCIDRs) > 0 +} + +// buildTCPIPFilterCheckFromLocalVars creates a filter using local vars $s0-$s3 and $d0-$d3. +// This is required because the BPF verifier doesn't allow reading from different +// offsets of args after a probe_read. We read bytes into local vars first, then filter. +// SECURITY: IPs are converted to integer byte values - no string interpolation. +func (g *ScriptGenerator) buildTCPIPFilterCheckFromLocalVars() string { + if len(g.config.FilterIPs) == 0 && len(g.config.FilterCIDRs) == 0 { + return "" // No filter + } + + var conditions []string + + // Add IP filters - compare using local vars + for _, ip := range g.config.FilterIPs { + ipv4 := ip.To4() + if ipv4 == nil { + continue + } + // Match either source or destination using local vars + conditions = append(conditions, fmt.Sprintf( + "(($s0 == %d && $s1 == %d && $s2 == %d && $s3 == %d) || ($d0 == %d && $d1 == %d && $d2 == %d && $d3 == %d))", + ipv4[0], ipv4[1], ipv4[2], ipv4[3], + ipv4[0], ipv4[1], ipv4[2], ipv4[3])) + } + + // Add CIDR filters - mask and compare using local vars + for _, cidr := range g.config.FilterCIDRs { + if cidr == nil { + continue + } + ipv4 := cidr.IP.To4() + mask := cidr.Mask + if ipv4 == nil || len(mask) != 4 { + continue + } + // (byte & mask) == network_byte for each byte + conditions = append(conditions, fmt.Sprintf( + "((($s0 & %d) == %d && ($s1 & %d) == %d && ($s2 & %d) == %d && ($s3 & %d) == %d) || (($d0 & %d) == %d && ($d1 & %d) == %d && ($d2 & %d) == %d && ($d3 & %d) == %d))", + mask[0], ipv4[0], mask[1], ipv4[1], mask[2], ipv4[2], mask[3], ipv4[3], + mask[0], ipv4[0], mask[1], ipv4[1], mask[2], ipv4[2], mask[3], ipv4[3])) + } + + if len(conditions) == 0 { + return "" + } + + // Generate an if-statement that returns early if no condition matches + combined := strings.Join(conditions, " || ") + return fmt.Sprintf(" // IP/CIDR filter: skip if not matching\n if (!(%s)) { return; }\n\n", combined) +} + +// generateTableOutput generates printf for table format. +func (g *ScriptGenerator) generateTableOutput() string { + return ` // Format source and destination with numeric reason code + if ($sport > 0) { + printf("%-12s %-10s %-18d %-18s %-18s %s:%-5d -> %s:%-5d\n", + strftime("%H:%M:%S", nsecs), + "DROP", + $reason, + "-", + "kfree_skb", + $saddr, $sport, + $daddr, $dport); + } else { + printf("%-12s %-10s %-18d %-18s %-18s %s -> %s\n", + strftime("%H:%M:%S", nsecs), + "DROP", + $reason, + "-", + "kfree_skb", + $saddr, + $daddr); + } +` +} + +// generateJSONOutput generates printf for JSON format. +func (g *ScriptGenerator) generateJSONOutput() string { + return ` // Output JSON with numeric reason code + printf("{\"time\":\"%s\",\"type\":\"DROP\",\"reason_code\":%d,\"probe\":\"kfree_skb\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", + strftime("%H:%M:%S", nsecs), + $reason, + $saddr, $sport, + $daddr, $dport); +` +} + +// generateEndBlock creates the END block. +func (g *ScriptGenerator) generateEndBlock() string { + if g.config.OutputJSON { + return `END { + printf("{\"event\":\"end\",\"message\":\"Trace complete\"}\n"); +} +` + } + return `END { + printf("\n────────────────────────────────────────────────────────────────────────────────────────────────────────────\n"); + printf("Trace complete.\n"); +} +` +} + +// buildSkbIPFilterCondition creates an if-statement to filter by IP inside kfree_skb body. +// This is used instead of a pre-filter because we need to parse the skb to get the IPs. +// SECURITY: IPs are converted to hex integers - no string interpolation of user input. +// +// IMPORTANT: $saddr_raw/$daddr_raw come from $iph->saddr which is __be32 (big-endian). +// bpftrace reads struct fields as native integers, so on little-endian (x86) the value +// is byte-swapped relative to network order. We use bswap() to convert back to network +// byte order before comparing with the big-endian hex constants from ipToHex(). +// This mirrors how $skb->protocol is handled: bswap($protocol) != 0x0800. +func (g *ScriptGenerator) buildSkbIPFilterCondition() string { + if len(g.config.FilterIPs) == 0 && len(g.config.FilterCIDRs) == 0 { + return "" // No filter + } + + var conditions []string + + // Add IP filters - compare against the raw uint32 IP values + // bswap() converts $saddr_raw from host byte order to network byte order + for _, ip := range g.config.FilterIPs { + ipv4 := ip.To4() + if ipv4 == nil { + continue + } + ipHex := ipToHex(ipv4) + // Match either source or destination (bswap to network byte order first) + conditions = append(conditions, fmt.Sprintf("(bswap($saddr_raw) == 0x%08x || bswap($daddr_raw) == 0x%08x)", ipHex, ipHex)) + } + + // Add CIDR filters - mask and compare + // bswap() converts to network byte order before masking + for _, cidr := range g.config.FilterCIDRs { + if cidr == nil { + continue + } + ipv4 := cidr.IP.To4() + if ipv4 == nil { + continue + } + networkHex := ipToHex(ipv4) + maskHex := ipToHex(net.IP(cidr.Mask).To4()) + conditions = append(conditions, fmt.Sprintf("((bswap($saddr_raw) & 0x%08x) == 0x%08x || (bswap($daddr_raw) & 0x%08x) == 0x%08x)", + maskHex, networkHex, maskHex, networkHex)) + } + + if len(conditions) == 0 { + return "" + } + + // Generate an if-statement that returns early if no condition matches + combined := strings.Join(conditions, " || ") + return fmt.Sprintf(" // IP/CIDR filter: skip if not matching\n if (!(%s)) { return; }\n\n", combined) +} + +// ipToHex converts an IPv4 address to a uint32 in network byte order. +// SECURITY: This function only outputs hex digits - no user input passes through. +func ipToHex(ip net.IP) uint32 { + ipv4 := ip.To4() + if ipv4 == nil { + return 0 + } + // Network byte order (big endian) - this matches how IPs are stored in IP headers + return binary.BigEndian.Uint32(ipv4) +} + +// DropReasonsCommand returns the command to fetch SKB drop reason enum from kernel. +// The enum values are kernel-version specific and must be read at runtime. +// This reads from the tracepoint format file which contains the enum definition. +func DropReasonsCommand() []string { + return []string{ + "sh", "-c", + `echo "=== SKB Drop Reason Codes (kernel-specific) ===" && ` + + `cat /sys/kernel/debug/tracing/events/skb/kfree_skb/format 2>/dev/null | ` + + `grep -oE '\{ [0-9]+, "[^"]+" \}' | ` + + `sed 's/{ \([0-9]*\), "\([^"]*\)" }/\1 = \2/' | ` + + `head -30 || ` + + `echo "(Could not read drop reasons - requires debugfs mounted)"`, + } +} diff --git a/shell/tracescript_test.go b/shell/tracescript_test.go new file mode 100644 index 0000000000..dd928859ab --- /dev/null +++ b/shell/tracescript_test.go @@ -0,0 +1,635 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package shell + +import ( + "net" + "strings" + "testing" +) + +func TestIPToHex(t *testing.T) { + tests := []struct { + name string + ip string + expected uint32 + }{ + { + name: "10.0.0.1", + ip: "10.0.0.1", + expected: 0x0a000001, + }, + { + name: "192.168.1.100", + ip: "192.168.1.100", + expected: 0xc0a80164, + }, + { + name: "0.0.0.0", + ip: "0.0.0.0", + expected: 0x00000000, + }, + { + name: "255.255.255.255", + ip: "255.255.255.255", + expected: 0xffffffff, + }, + { + name: "127.0.0.1", + ip: "127.0.0.1", + expected: 0x7f000001, + }, + { + name: "172.16.0.1", + ip: "172.16.0.1", + expected: 0xac100001, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ip := net.ParseIP(tt.ip) + if ip == nil { + t.Fatalf("failed to parse IP: %s", tt.ip) + } + result := ipToHex(ip) + if result != tt.expected { + t.Errorf("ipToHex(%s) = 0x%08x, want 0x%08x", tt.ip, result, tt.expected) + } + }) + } +} + +func TestIPToHexOnlyHexOutput(t *testing.T) { + // SECURITY TEST: Verify that output only contains hex digits + // This ensures no injection is possible through IP addresses + ips := []string{ + "10.0.0.1", + "192.168.1.100", + "172.16.255.255", + "0.0.0.0", + "255.255.255.255", + } + + for _, ipStr := range ips { + ip := net.ParseIP(ipStr) + if ip == nil { + t.Fatalf("failed to parse IP: %s", ipStr) + } + + hex := ipToHex(ip) + // Convert to string representation + formatted := strings.ToLower(string([]byte{ + '0', 'x', + hexChar((hex >> 28) & 0xf), + hexChar((hex >> 24) & 0xf), + hexChar((hex >> 20) & 0xf), + hexChar((hex >> 16) & 0xf), + hexChar((hex >> 12) & 0xf), + hexChar((hex >> 8) & 0xf), + hexChar((hex >> 4) & 0xf), + hexChar(hex & 0xf), + })) + + // Verify only contains 0-9, a-f, x + for _, c := range formatted { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') && c != 'x' { + t.Errorf("ipToHex(%s) produced non-hex character: %c in %s", ipStr, c, formatted) + } + } + } +} + +func hexChar(b uint32) byte { + // Mask to 4 bits to guarantee 0-15 range and prevent G115 overflow. + n := byte(b & 0xf) + if n < 10 { + return '0' + n + } + return 'a' + n - 10 +} + +func TestGenerateDropScript(t *testing.T) { + config := TraceConfig{ + EnableDrops: true, + EnableRST: true, + EnableErrors: true, + EnableRetransmits: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Verify script structure + if !strings.Contains(script, "#!/usr/bin/env bpftrace") { + t.Error("script missing shebang") + } + if !strings.Contains(script, "tracepoint:skb:kfree_skb") { + t.Error("script missing kfree_skb tracepoint") + } + if !strings.Contains(script, "BEGIN {") { + t.Error("script missing BEGIN block") + } + if !strings.Contains(script, "END {") { + t.Error("script missing END block") + } + if !strings.Contains(script, "$reason") { + t.Error("script missing reason variable") + } + if !strings.Contains(script, "DROP") { + t.Error("script missing DROP output") + } +} + +func TestGenerateDropScriptNoFilter(t *testing.T) { + config := TraceConfig{ + EnableDrops: true, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + // No filter should be empty + if filter != "" { + t.Errorf("expected empty filter, got: %s", filter) + } +} + +func TestGenerateDropScriptWithIPFilter(t *testing.T) { + ip := net.ParseIP("10.0.0.1") + config := TraceConfig{ + FilterIPs: []net.IP{ip}, + OutputJSON: false, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + // Should contain hex representation + if !strings.Contains(filter, "0x0a000001") { + t.Errorf("expected filter to contain hex IP 0x0a000001, got: %s", filter) + } + + // Should use bswap() to handle endianness (kfree_skb reads __be32 as native int) + if !strings.Contains(filter, "bswap($saddr_raw)") || !strings.Contains(filter, "bswap($daddr_raw)") { + t.Errorf("expected filter to use bswap() for endianness conversion, got: %s", filter) + } + + // Should NOT contain the original IP string (security check) + if strings.Contains(filter, "10.0.0.1") { + t.Error("filter should not contain original IP string - security risk") + } +} + +func TestGenerateDropScriptWithCIDRFilter(t *testing.T) { + _, cidr, err := net.ParseCIDR("10.0.0.0/24") + if err != nil { + t.Fatalf("failed to parse CIDR: %v", err) + } + + config := TraceConfig{ + FilterCIDRs: []*net.IPNet{cidr}, + OutputJSON: false, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + // Should contain hex network + if !strings.Contains(filter, "0x0a000000") { + t.Errorf("expected filter to contain hex network 0x0a000000, got: %s", filter) + } + + // Should contain hex mask for /24 + if !strings.Contains(filter, "0xffffff00") { + t.Errorf("expected filter to contain hex mask 0xffffff00, got: %s", filter) + } + + // Should use bswap() for endianness + if !strings.Contains(filter, "bswap($saddr_raw)") { + t.Errorf("expected filter to use bswap() for endianness conversion, got: %s", filter) + } +} + +func TestGenerateDropScriptJSONOutput(t *testing.T) { + config := TraceConfig{ + OutputJSON: true, + EnableDrops: true, + EnableRST: true, + EnableErrors: true, + EnableRetransmits: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // JSON output should have JSON-formatted printf statements + // Note: In the bpftrace script, quotes are escaped with backslash + if !strings.Contains(script, `\"type\":\"DROP\"`) { + t.Error("JSON script missing DROP type field") + } + if !strings.Contains(script, `\"reason_code\"`) { + t.Error("JSON script missing reason_code field") + } + if !strings.Contains(script, `\"src_ip\"`) { + t.Error("JSON script missing src_ip field") + } +} + +func TestGenerateDropScriptTableOutput(t *testing.T) { + config := TraceConfig{ + EnableDrops: true, + EnableRST: true, + EnableErrors: true, + EnableRetransmits: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Table output should have header + if !strings.Contains(script, "TIME") { + t.Error("table script missing TIME header") + } + if !strings.Contains(script, "TYPE") { + t.Error("table script missing TYPE header") + } + if !strings.Contains(script, "REASON") { + t.Error("table script missing REASON header") + } + if !strings.Contains(script, "STATE") { + t.Error("table script missing STATE header") + } + if !strings.Contains(script, "PROBE") { + t.Error("table script missing PROBE header") + } +} + +func TestScriptGeneratorNoUserStringInterpolation(t *testing.T) { + // SECURITY TEST: Verify that user-provided values are never + // directly interpolated as strings into the script + + // Try various concerning inputs - all should be rejected by validation + // but even if they made it here, they should be safe + + // Create a generator with an IP that could be injection attempt + // Note: This IP is valid but we verify it's converted to hex + ip := net.ParseIP("127.0.0.1") + config := TraceConfig{ + FilterIPs: []net.IP{ip}, + OutputJSON: false, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + // The node name should NOT appear in the filter + if strings.Contains(filter, "evil-node") { + t.Error("node name should not appear in filter condition") + } + + // The filter should only contain safe characters + // Allow: hex digits, whitespace, operators, struct names, etc. + // Disallow: semicolons, backticks, $() syntax + dangerousPatterns := []string{ + "`;", + "$()", + "`", + "system(", + "exec(", + } + + for _, pattern := range dangerousPatterns { + if strings.Contains(filter, pattern) { + t.Errorf("filter contains dangerous pattern: %s", pattern) + } + } +} + +func TestBuildIPFilter(t *testing.T) { + tests := []struct { + name string + ips []string + expectHexIPs []string + noStringIPs bool // Verify original strings don't appear + }{ + { + name: "single IP", + ips: []string{"10.0.0.1"}, + expectHexIPs: []string{"0x0a000001"}, + noStringIPs: true, + }, + { + name: "multiple IPs", + ips: []string{"10.0.0.1", "192.168.1.1"}, + expectHexIPs: []string{"0x0a000001", "0xc0a80101"}, + noStringIPs: true, + }, + { + name: "Class B network", + ips: []string{"172.16.0.1"}, + expectHexIPs: []string{"0xac100001"}, + noStringIPs: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var parsedIPs []net.IP + for _, ipStr := range tt.ips { + ip := net.ParseIP(ipStr) + if ip == nil { + t.Fatalf("failed to parse IP: %s", ipStr) + } + parsedIPs = append(parsedIPs, ip) + } + + config := TraceConfig{ + FilterIPs: parsedIPs, + OutputJSON: false, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + // Verify hex IPs are present + for _, hexIP := range tt.expectHexIPs { + if !strings.Contains(filter, hexIP) { + t.Errorf("expected filter to contain %s, got: %s", hexIP, filter) + } + } + + // Verify original string IPs are NOT present (security) + if tt.noStringIPs { + for _, ipStr := range tt.ips { + if strings.Contains(filter, ipStr) { + t.Errorf("filter should not contain original IP string %s - security risk", ipStr) + } + } + } + }) + } +} + +func TestBuildCIDRFilter(t *testing.T) { + tests := []struct { + name string + cidr string + expectNet string // hex network address + expectMask string // hex mask + }{ + { + name: "/24 network", + cidr: "10.0.0.0/24", + expectNet: "0x0a000000", + expectMask: "0xffffff00", + }, + { + name: "/16 network", + cidr: "172.16.0.0/16", + expectNet: "0xac100000", + expectMask: "0xffff0000", + }, + { + name: "/8 network", + cidr: "10.0.0.0/8", + expectNet: "0x0a000000", + expectMask: "0xff000000", + }, + { + name: "/32 single host", + cidr: "192.168.1.100/32", + expectNet: "0xc0a80164", + expectMask: "0xffffffff", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, cidr, err := net.ParseCIDR(tt.cidr) + if err != nil { + t.Fatalf("failed to parse CIDR: %v", err) + } + + config := TraceConfig{ + FilterCIDRs: []*net.IPNet{cidr}, + OutputJSON: false, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + if !strings.Contains(filter, tt.expectNet) { + t.Errorf("expected filter to contain network %s, got: %s", tt.expectNet, filter) + } + if !strings.Contains(filter, tt.expectMask) { + t.Errorf("expected filter to contain mask %s, got: %s", tt.expectMask, filter) + } + }) + } +} + +func TestMixedIPAndCIDRFilter(t *testing.T) { + ip := net.ParseIP("10.0.0.1") + _, cidr, _ := net.ParseCIDR("192.168.0.0/16") + + config := TraceConfig{ + FilterIPs: []net.IP{ip}, + FilterCIDRs: []*net.IPNet{cidr}, + OutputJSON: false, + } + + gen := NewScriptGenerator(config) + filter := gen.buildSkbIPFilterCondition() + + // Should contain both IP and CIDR hex values + if !strings.Contains(filter, "0x0a000001") { + t.Error("filter missing IP hex value") + } + if !strings.Contains(filter, "0xc0a80000") { + t.Error("filter missing CIDR network hex value") + } + + // Conditions should be combined with OR + if !strings.Contains(filter, "||") { + t.Error("filter should combine conditions with OR") + } +} + +func TestDropReasonsCommand(t *testing.T) { + cmd := DropReasonsCommand() + + // Should be a shell command + if len(cmd) != 3 { + t.Errorf("expected 3 elements (sh -c cmd), got %d", len(cmd)) + } + if cmd[0] != "sh" || cmd[1] != "-c" { + t.Error("expected sh -c prefix") + } + + // Should read from the tracepoint format file + if !strings.Contains(cmd[2], "kfree_skb/format") { + t.Error("command should read from kfree_skb/format") + } + + // Should have fallback message + if !strings.Contains(cmd[2], "Could not read") { + t.Error("command should have fallback error message") + } +} + +func TestScriptUsesNumericReasonCode(t *testing.T) { + config := TraceConfig{ + EnableDrops: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Script should NOT contain hardcoded reason names + hardcodedReasons := []string{ + "NO_SOCKET", + "NETFILTER_DROP", + "OTHERHOST", + } + + for _, reason := range hardcodedReasons { + if strings.Contains(script, reason) { + t.Errorf("script should not hardcode reason name: %s", reason) + } + } + + // Script should use $reason (numeric) in output + if !strings.Contains(script, "$reason") { + t.Error("script should use $reason variable for numeric code") + } +} + +func TestGenerateNfqueueDropProbe(t *testing.T) { + config := TraceConfig{ + EnableNfqueueDrops: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Verify fexit probe is present + if !strings.Contains(script, "fexit:vmlinux:__nf_queue") { + t.Error("script missing fexit:vmlinux:__nf_queue probe") + } + + // Verify it checks return value + if !strings.Contains(script, "retval") { + t.Error("script missing retval check") + } + + // Verify it accesses args->skb + if !strings.Contains(script, "args->skb") { + t.Error("script missing args->skb access") + } + + // Verify it reads queue number + if !strings.Contains(script, "args->queuenum") { + t.Error("script missing args->queuenum access") + } + + // Verify NFQ_DROP event type in table output + if !strings.Contains(script, "NFQ_DROP") { + t.Error("script missing NFQ_DROP event type") + } + + // Verify __nf_queue probe name in output + if !strings.Contains(script, "__nf_queue") { + t.Error("script missing __nf_queue probe name in output") + } + + // Verify errno decoding + if !strings.Contains(script, "ESRCH") { + t.Error("script missing ESRCH errno name") + } + if !strings.Contains(script, "ENOMEM") { + t.Error("script missing ENOMEM errno name") + } +} + +func TestGenerateNfqueueDropProbeJSON(t *testing.T) { + config := TraceConfig{ + EnableNfqueueDrops: true, + OutputJSON: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Verify JSON output fields + if !strings.Contains(script, `\"type\":\"NFQ_DROP\"`) { + t.Error("JSON script missing NFQ_DROP type field") + } + if !strings.Contains(script, `\"queue\"`) { + t.Error("JSON script missing queue field") + } + if !strings.Contains(script, `\"errno\"`) { + t.Error("JSON script missing errno field") + } + if !strings.Contains(script, `\"probe\":\"__nf_queue\"`) { + t.Error("JSON script missing __nf_queue probe field") + } +} + +func TestGenerateNfqueueDropProbeWithIPFilter(t *testing.T) { + ip := net.ParseIP("10.0.0.1") + config := TraceConfig{ + EnableNfqueueDrops: true, + FilterIPs: []net.IP{ip}, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // Should contain fexit probe + if !strings.Contains(script, "fexit:vmlinux:__nf_queue") { + t.Error("script missing fexit probe") + } + + // Should contain IP filter hex + if !strings.Contains(script, "0x0a000001") { + t.Error("script missing hex IP in NFQUEUE probe filter") + } + + // Should use bswap for filter + if !strings.Contains(script, "bswap($saddr_raw)") { + t.Error("script missing bswap in NFQUEUE probe filter") + } +} + +func TestGenerateAllProbesIncludingNfqueue(t *testing.T) { + // Verify all probes can be generated together + config := TraceConfig{ + EnableDrops: true, + EnableRST: true, + EnableErrors: true, + EnableRetransmits: true, + EnableNfqueueDrops: true, + } + + gen := NewScriptGenerator(config) + script := gen.Generate() + + // All probes should be present + if !strings.Contains(script, "tracepoint:skb:kfree_skb") { + t.Error("script missing kfree_skb probe") + } + if !strings.Contains(script, "tcp_send_reset") { + t.Error("script missing RST probe") + } + if !strings.Contains(script, "inet_sk_error_report") { + t.Error("script missing socket error probe") + } + if !strings.Contains(script, "tcp_retransmit_skb") { + t.Error("script missing retransmit probe") + } + if !strings.Contains(script, "fexit:vmlinux:__nf_queue") { + t.Error("script missing NFQUEUE probe") + } +} diff --git a/test/e2e/test_bpftrace_drops.sh b/test/e2e/test_bpftrace_drops.sh new file mode 100755 index 0000000000..4156c51f86 --- /dev/null +++ b/test/e2e/test_bpftrace_drops.sh @@ -0,0 +1,226 @@ +#!/bin/bash +# Test script for bpftrace - tests drops, RST, socket errors, and retransmits +# Usage: ./test_bpftrace_drops.sh [kubeconfig_path] +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +echo "=== Bpftrace Network Issue Detection Test ===" +echo "" + +# Get first node +NODE=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') +echo "Target node: $NODE" + +# Clean up any leftover test pods +echo "Cleaning up previous test pods..." +kubectl delete pod drop-gen rst-gen nfqueue-helper --force --grace-period=0 2>/dev/null || true +kubectl delete pod -l app=retina-trace --force --grace-period=0 2>/dev/null || true +sleep 2 + +# Build CLI if needed +if [[ ! -f "$REPO_ROOT/kubectl-retina" ]]; then + echo "Building kubectl-retina..." + cd "$REPO_ROOT" + go build -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=v1.0.3" -o kubectl-retina ./cli/main.go +fi + +echo "" +echo "=== Starting bpftrace (70s duration) ===" +echo "This will capture drops, RST, socket errors, retransmits, and NFQUEUE drops on $NODE" +echo "" + +# Create output file +OUTPUT_FILE=$(mktemp) +trap "rm -f $OUTPUT_FILE" EXIT + +# Run trace in background and capture output +# Duration must be long enough for all test phases: RST, DROP/RETRANS, and NFQUEUE +# (each phase takes ~15-30s including pod startup and traffic generation) +"$REPO_ROOT/kubectl-retina" bpftrace "$NODE" --duration 70s --startup-timeout 120s --retina-shell-image-version v1.0.3 > "$OUTPUT_FILE" 2>&1 & +TRACE_PID=$! + +# Wait for trace to start +echo "Waiting for trace pod to start..." +sleep 15 + +echo "" +echo "=== Test 1: RST and SOCK_ERR (connection refused) ===" +# Connect to a closed port to generate RST and socket error (ECONNREFUSED=111) +kubectl run rst-gen --rm -i --restart=Never --image=busybox --overrides="{\"spec\":{\"nodeName\":\"$NODE\"}}" -- sh -c " +for i in 1 2 3; do + echo \"RST attempt \$i: connecting to closed port 9999\" + nc -zv -w1 127.0.0.1 9999 2>&1 || true + sleep 0.5 +done +echo 'RST generation complete' +" 2>&1 || true + +echo "" +echo "=== Test 2: DROP and RETRANS (NetworkPolicy block) ===" +# NetworkPolicy drops will cause TCP to retransmit SYN packets + +# Create a NetworkPolicy to block traffic +cat </dev/null || true +sleep 5 +kubectl wait --for=condition=Ready pod/drop-target --timeout=30s 2>/dev/null || true + +TARGET_IP=$(kubectl get pod drop-target -o jsonpath='{.status.podIP}' 2>/dev/null || echo "10.244.0.99") +echo "Target IP: $TARGET_IP" + +# Generate blocked traffic - connection attempts will retransmit SYN packets +echo "Sending blocked traffic (will cause retransmissions)..." +kubectl run drop-gen --rm -i --restart=Never --image=busybox --overrides="{\"spec\":{\"nodeName\":\"$NODE\"}}" -- sh -c " +for i in 1 2 3 4 5; do + echo \"Attempt \$i to $TARGET_IP:80\" + nc -zv -w2 $TARGET_IP 80 2>&1 || true + sleep 0.5 +done +echo 'Traffic generation complete' +" 2>&1 || true + +echo "" +echo "=== Test 3: NFQ_DROP (iptables NFQUEUE with no consumer) ===" +# Add an iptables -j NFQUEUE rule pointing to a queue with no reader. +# The kernel calls __nf_queue which returns -ESRCH, and fexit catches it. +echo "Creating privileged pod to add NFQUEUE iptables rule..." +cat </dev/null 2>&1 + echo "Adding NFQUEUE rule on OUTPUT to $TARGET_IP:80 queue 42 (no consumer)..." + iptables -I OUTPUT -d $TARGET_IP -p tcp --dport 80 -j NFQUEUE --queue-num 42 + for i in 1 2 3 4 5; do + echo "attempt \$i: connecting to $TARGET_IP:80 via NFQUEUE..." + nc -zv -w2 $TARGET_IP 80 2>&1 || true + sleep 0.5 + done + echo "Removing NFQUEUE rule..." + iptables -D OUTPUT -d $TARGET_IP -p tcp --dport 80 -j NFQUEUE --queue-num 42 2>/dev/null + echo "NFQUEUE test done" +EOF +kubectl wait --for=condition=Ready pod/nfqueue-helper --timeout=60s 2>/dev/null || true +kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/nfqueue-helper --timeout=60s 2>/dev/null || true +kubectl logs nfqueue-helper 2>/dev/null || true +kubectl delete pod nfqueue-helper --force --grace-period=0 2>/dev/null || true + +echo "" +echo "=== Waiting for trace to complete ===" +wait $TRACE_PID || true + +echo "" +echo "=== Trace Output ===" +cat "$OUTPUT_FILE" + +echo "" +echo "=== Cleanup ===" +kubectl delete networkpolicy deny-all-test 2>/dev/null || true +kubectl delete pod drop-target --force --grace-period=0 2>/dev/null || true +kubectl delete pod nfqueue-helper --force --grace-period=0 2>/dev/null || true +kubectl delete pod -l app=retina-trace --force --grace-period=0 2>/dev/null || true + +echo "" +echo "=== Test Complete ===" + +# Check results. +# Use precise patterns to match actual event output lines and avoid false +# positives from verbose/startup logs that may mention these keywords. +DROPS_FOUND=false +RST_FOUND=false +SOCK_ERR_FOUND=false +RETRANS_FOUND=false +NFQ_DROP_FOUND=false + +if grep -qP '\bDROP\b.*kfree_skb' "$OUTPUT_FILE"; then + DROPS_FOUND=true + echo "✓ DROP events captured" +else + echo "✗ DROP events NOT captured (requires cluster NetworkPolicy support)" +fi + +if grep -qP '\bRST_(SENT|RECV)\b' "$OUTPUT_FILE"; then + RST_FOUND=true + echo "✓ RST events captured" +else + echo "✗ RST events NOT captured" +fi + +if grep -qP '\bSOCK_ERR\b.*inet_sk_error_report' "$OUTPUT_FILE"; then + SOCK_ERR_FOUND=true + echo "✓ SOCK_ERR events captured" +else + echo "✗ SOCK_ERR events NOT captured" +fi + +if grep -qP '\bRETRANS\b.*tcp_retransmit_skb' "$OUTPUT_FILE"; then + RETRANS_FOUND=true + echo "✓ RETRANS events captured" +else + echo "✗ RETRANS events NOT captured" +fi + +if grep -qP '\bNFQ_DROP\b.*__nf_queue' "$OUTPUT_FILE"; then + NFQ_DROP_FOUND=true + echo "✓ NFQ_DROP events captured" +else + echo "✗ NFQ_DROP events NOT captured (requires iptables/NFQUEUE support)" +fi + +# Count successes +SUCCESSES=0 +$DROPS_FOUND && ((SUCCESSES++)) || true +$RST_FOUND && ((SUCCESSES++)) || true +$SOCK_ERR_FOUND && ((SUCCESSES++)) || true +$RETRANS_FOUND && ((SUCCESSES++)) || true +$NFQ_DROP_FOUND && ((SUCCESSES++)) || true + +if [ $SUCCESSES -ge 3 ]; then + echo "" + echo "SUCCESS: $SUCCESSES/5 event types captured!" + exit 0 +elif [ $SUCCESSES -ge 1 ]; then + echo "" + echo "PARTIAL SUCCESS: $SUCCESSES/5 event types captured" + echo "Note: Some events may not occur depending on kernel behavior" + exit 0 +else + echo "" + echo "NOTE: No events captured. This may be expected if:" + echo " - The kernel doesn't trigger these tracepoints" + echo " - Traffic was blocked before reaching the tracepoints" + echo " - Try running manually with different traffic patterns" + exit 0 +fi diff --git a/test/e2e/test_bpftrace_filter_ip.sh b/test/e2e/test_bpftrace_filter_ip.sh new file mode 100755 index 0000000000..db3a3e2e58 --- /dev/null +++ b/test/e2e/test_bpftrace_filter_ip.sh @@ -0,0 +1,317 @@ +#!/bin/bash +# Test script for bpftrace --ip flag +# This validates that IP filtering works correctly in bpftrace scripts +# Tests drops, RST, socket errors, and retransmits with --ip filtering +# Usage: ./test_bpftrace_filter_ip.sh [kubeconfig_path] +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +echo "=== Bpftrace --ip Flag Test ===" +echo "" + +# Get first node +NODE=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') +echo "Target node: $NODE" + +# Clean up any leftover test pods +echo "Cleaning up previous test pods..." +kubectl delete pod drop-gen rst-gen traffic-gen filter-test-target nfqueue-helper --force --grace-period=0 2>/dev/null || true +kubectl delete pod -l app=retina-trace --force --grace-period=0 2>/dev/null || true +kubectl delete networkpolicy deny-all-filter-ip-test 2>/dev/null || true +sleep 2 + +# Build CLI if needed +if [[ ! -f "$REPO_ROOT/kubectl-retina" ]]; then + echo "Building kubectl-retina..." + cd "$REPO_ROOT" + go build -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version=v1.0.3" -o kubectl-retina ./cli/main.go +fi + +# Create a test pod to get a stable IP for filtering +echo "Creating test target pod..." +kubectl run filter-test-target --image=nginx --labels="app=filter-test-target" --overrides="{\"spec\":{\"nodeName\":\"$NODE\"}}" 2>/dev/null || true +sleep 5 +kubectl wait --for=condition=Ready pod/filter-test-target --timeout=60s 2>/dev/null || true + +TARGET_IP=$(kubectl get pod filter-test-target -o jsonpath='{.status.podIP}') +if [[ -z "$TARGET_IP" ]]; then + echo "ERROR: Could not get target pod IP" + exit 1 +fi +echo "Target pod IP: $TARGET_IP" + +echo "" +echo "=== Starting bpftrace with --ip $TARGET_IP (70s duration) ===" +echo "This will capture drops, RST, socket errors, retransmits, and NFQUEUE drops filtered to $TARGET_IP on $NODE" +echo "" + +# Create output files +OUTPUT_FILE=$(mktemp) +ERROR_FILE=$(mktemp) +trap "rm -f $OUTPUT_FILE $ERROR_FILE; kubectl delete networkpolicy deny-all-filter-ip-test 2>/dev/null || true; kubectl delete pod filter-test-target nfqueue-helper --force --grace-period=0 2>/dev/null || true; kubectl delete pod -l app=retina-trace --force --grace-period=0 2>/dev/null || true" EXIT + +# Run trace with IP filter in background and capture output +# Duration must be long enough for all test phases: RST, DROP/RETRANS, NFQUEUE, extra traffic +# (each phase takes ~15-30s including pod startup and traffic generation) +"$REPO_ROOT/kubectl-retina" bpftrace "$NODE" --duration 70s --startup-timeout 120s \ + --ip "$TARGET_IP" \ + --retina-shell-image-version v1.0.3 > "$OUTPUT_FILE" 2>"$ERROR_FILE" & +TRACE_PID=$! + +# Wait for trace to start +echo "Waiting for trace pod to start..." +sleep 15 + +echo "" +echo "=== Test 1: RST and SOCK_ERR (connection refused via target IP) ===" +# Connect to the target pod on a closed port to generate RST and socket error +kubectl run rst-gen --rm -i --restart=Never --image=busybox --overrides="{\"spec\":{\"nodeName\":\"$NODE\"}}" -- sh -c " +for i in 1 2 3; do + echo \"RST attempt \$i: connecting to $TARGET_IP on closed port 9999\" + nc -zv -w1 $TARGET_IP 9999 2>&1 || true + sleep 0.5 +done +echo 'RST generation complete' +" 2>&1 || true + +echo "" +echo "=== Test 2: DROP and RETRANS (NetworkPolicy block on filtered IP) ===" +# Apply a deny-all NetworkPolicy to filter-test-target itself so that +# subsequent traffic to TARGET_IP is dropped and retransmitted. +# This ensures DROP and RETRANS events occur on the IP we're filtering. + +cat <&1 || true + sleep 0.5 +done +echo 'Traffic generation complete' +" 2>&1 || true + +echo "" +echo "=== Test 3: NFQ_DROP with IP filter ===" +# Add an iptables -j NFQUEUE rule for traffic to TARGET_IP; no consumer on queue. +# The fexit:vmlinux:__nf_queue probe should capture the drop and the IP filter +# should ensure only events involving TARGET_IP appear. +# NOTE: This test runs before the "additional traffic" test to ensure it completes +# within the trace window. The nfqueue-helper pod needs time to install iptables. +echo "Creating privileged pod to add NFQUEUE iptables rule..." +cat </dev/null 2>&1 + echo "Adding NFQUEUE rule on OUTPUT to $TARGET_IP:80 queue 42 (no consumer)..." + iptables -I OUTPUT -d $TARGET_IP -p tcp --dport 80 -j NFQUEUE --queue-num 42 + for i in 1 2 3 4 5; do + echo "attempt \$i: connecting to $TARGET_IP:80 via NFQUEUE..." + nc -zv -w2 $TARGET_IP 80 2>&1 || true + sleep 0.5 + done + echo "Removing NFQUEUE rule..." + iptables -D OUTPUT -d $TARGET_IP -p tcp --dport 80 -j NFQUEUE --queue-num 42 2>/dev/null + echo "NFQUEUE test done" +EOF +kubectl wait --for=condition=Ready pod/nfqueue-helper --timeout=60s 2>/dev/null || true +kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/nfqueue-helper --timeout=60s 2>/dev/null || true +kubectl logs nfqueue-helper 2>/dev/null || true +kubectl delete pod nfqueue-helper --force --grace-period=0 2>/dev/null || true + +echo "" +echo "=== Test 4: Additional traffic to filtered IP ===" +# Generate extra traffic to the filtered IP to increase chances of capture +echo "Generating additional traffic to $TARGET_IP..." +kubectl run traffic-gen --rm -i --restart=Never --image=busybox --overrides="{\"spec\":{\"nodeName\":\"$NODE\"}}" -- sh -c " +for i in 1 2 3 4 5; do + echo \"Attempt \$i: connecting to $TARGET_IP:80\" + wget -q -O /dev/null -T 2 http://$TARGET_IP:80/ 2>&1 || true + echo \"Attempt \$i: connecting to $TARGET_IP:9999 (closed port)\" + nc -zv -w1 $TARGET_IP 9999 2>&1 || true + sleep 1 +done +echo 'Traffic generation complete' +" 2>&1 || true + +echo "" +echo "=== Waiting for trace to complete ===" +wait $TRACE_PID 2>/dev/null || true + +echo "" +echo "=== Trace Output ===" +cat "$OUTPUT_FILE" + +echo "" +echo "=== Error Output ===" +cat "$ERROR_FILE" + +echo "" +echo "=== Cleanup ===" +kubectl delete networkpolicy deny-all-filter-ip-test 2>/dev/null || true +kubectl delete pod filter-test-target nfqueue-helper --force --grace-period=0 2>/dev/null || true +kubectl delete pod -l app=retina-trace --force --grace-period=0 2>/dev/null || true + +echo "" +echo "=== Test Results ===" + +# Check for the specific casting error that was previously seen +CAST_ERROR=false +if grep -q "Cannot cast from" "$ERROR_FILE" || grep -q "Cannot cast from" "$OUTPUT_FILE"; then + CAST_ERROR=true + echo "✗ FAIL: bpftrace cast error detected" + echo " The --ip flag is generating invalid bpftrace code" +fi + +if [[ "$CAST_ERROR" == "true" ]]; then + echo "" + echo "TEST FAILED: bpftrace casting error" + echo "The --ip flag is generating code that bpftrace cannot execute." + exit 1 +fi + +# Check if the trace started successfully +TRACE_STARTED=false +if grep -q "Tracing network issues" "$OUTPUT_FILE"; then + TRACE_STARTED=true + echo "✓ Trace started successfully with --ip filter" +fi + +# Check for the filtered IP in the output (shows filter was applied) +FILTER_APPLIED=false +if grep -q "$TARGET_IP" "$ERROR_FILE" 2>/dev/null || grep -qi "filter" "$OUTPUT_FILE" 2>/dev/null; then + FILTER_APPLIED=true + echo "✓ IP filter was applied for $TARGET_IP" +fi + +# Verify each event type was captured AND contains the filtered IP on the same line. +DROPS_FOUND=false +RST_FOUND=false +SOCK_ERR_FOUND=false +RETRANS_FOUND=false +NFQ_DROP_FOUND=false + +if grep -qP '\bDROP\b.*kfree_skb' "$OUTPUT_FILE"; then + if grep -P '\bDROP\b.*kfree_skb' "$OUTPUT_FILE" | grep -qF "$TARGET_IP"; then + DROPS_FOUND=true + echo "✓ DROP events captured for $TARGET_IP" + else + echo "✗ DROP events captured but NOT for filtered IP $TARGET_IP — filter may be broken" + fi +else + echo "✗ DROP events NOT captured (requires cluster NetworkPolicy support)" +fi + +if grep -qP '\bRST_(SENT|RECV)\b' "$OUTPUT_FILE"; then + if grep -P '\bRST_(SENT|RECV)\b' "$OUTPUT_FILE" | grep -qF "$TARGET_IP"; then + RST_FOUND=true + echo "✓ RST events captured for $TARGET_IP" + else + echo "✗ RST events captured but NOT for filtered IP $TARGET_IP — filter may be broken" + fi +else + echo "✗ RST events NOT captured" +fi + +if grep -qP '\bSOCK_ERR\b.*inet_sk_error_report' "$OUTPUT_FILE"; then + if grep -P '\bSOCK_ERR\b.*inet_sk_error_report' "$OUTPUT_FILE" | grep -qF "$TARGET_IP"; then + SOCK_ERR_FOUND=true + echo "✓ SOCK_ERR events captured for $TARGET_IP" + else + echo "✗ SOCK_ERR events captured but NOT for filtered IP $TARGET_IP — filter may be broken" + fi +else + echo "✗ SOCK_ERR events NOT captured" +fi + +if grep -qP '\bRETRANS\b.*tcp_retransmit_skb' "$OUTPUT_FILE"; then + if grep -P '\bRETRANS\b.*tcp_retransmit_skb' "$OUTPUT_FILE" | grep -qF "$TARGET_IP"; then + RETRANS_FOUND=true + echo "✓ RETRANS events captured for $TARGET_IP" + else + echo "✗ RETRANS events captured but NOT for filtered IP $TARGET_IP — filter may be broken" + fi +else + echo "✗ RETRANS events NOT captured" +fi + +if grep -qP '\bNFQ_DROP\b.*__nf_queue' "$OUTPUT_FILE"; then + if grep -P '\bNFQ_DROP\b.*__nf_queue' "$OUTPUT_FILE" | grep -qF "$TARGET_IP"; then + NFQ_DROP_FOUND=true + echo "✓ NFQ_DROP events captured for $TARGET_IP" + else + echo "✗ NFQ_DROP events captured but NOT for filtered IP $TARGET_IP — filter may be broken" + fi +else + echo "✗ NFQ_DROP events NOT captured (requires iptables/NFQUEUE support)" +fi + +# Count successes +SUCCESSES=0 +$DROPS_FOUND && ((SUCCESSES++)) || true +$RST_FOUND && ((SUCCESSES++)) || true +$SOCK_ERR_FOUND && ((SUCCESSES++)) || true +$RETRANS_FOUND && ((SUCCESSES++)) || true +$NFQ_DROP_FOUND && ((SUCCESSES++)) || true + +if [[ "$TRACE_STARTED" != "true" ]]; then + echo "" + echo "TEST INCONCLUSIVE: Trace may not have started" + echo "Check the output above for details" + exit 1 +fi + +if [ $SUCCESSES -ge 3 ]; then + echo "" + echo "SUCCESS: $SUCCESSES/5 event types captured with --ip filter!" + exit 0 +elif [ $SUCCESSES -ge 1 ]; then + echo "" + echo "PARTIAL SUCCESS: $SUCCESSES/5 event types captured with --ip filter" + echo "Note: Some events may not occur depending on kernel behavior" + exit 0 +else + echo "" + echo "NOTE: No events captured with --ip filter. This may be expected if:" + echo " - The kernel doesn't trigger these tracepoints for the filtered IP" + echo " - Traffic was blocked before reaching the tracepoints" + echo " - The IP filter is too restrictive for the generated traffic" + echo " - Try running manually with different traffic patterns" + exit 0 +fi From 4bac33a72d0fdd96da2de655dc5e2a28604d0ceb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:47:54 -0500 Subject: [PATCH 221/448] chore(deps): bump ajv from 6.12.6 to 6.14.0 in /site in the npm_and_yarn group across 1 directory (#2070) Bumps the npm_and_yarn group with 1 update in the /site directory: [ajv](https://github.com/ajv-validator/ajv). Updates `ajv` from 6.12.6 to 6.14.0
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ajv&package-manager=npm_and_yarn&previous-version=6.12.6&new-version=6.14.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 05452350e9..92409f9f92 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -5909,9 +5909,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -9102,9 +9102,9 @@ } }, "node_modules/file-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -13729,9 +13729,9 @@ } }, "node_modules/null-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -18656,9 +18656,9 @@ } }, "node_modules/url-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", From 5cda78b54ad977f41bb4b7815685b8f3295d6dca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:37:39 -0500 Subject: [PATCH 222/448] deps: bump github/codeql-action from 4.32.3 to 4.32.4 (#2072) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.3 to 4.32.4.
Release notes

Sourced from github/codeql-action's releases.

v4.32.4

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473
  • When the CodeQL Action is run with debugging enabled in Default Setup and private package registries are configured, the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. #3486
  • Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. #3485
  • Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a nightly CodeQL CLI release instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. #3484
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.32.4 - 20 Feb 2026

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473
  • When the CodeQL Action is run with debugging enabled in Default Setup and private package registries are configured, the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. #3486
  • Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. #3485
  • Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a nightly CodeQL CLI release instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. #3484

4.32.3 - 13 Feb 2026

  • Added experimental support for testing connections to private package registries. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. #3466

4.32.2 - 05 Feb 2026

  • Update default CodeQL bundle version to 2.24.1. #3460

4.32.1 - 02 Feb 2026

  • A warning is now shown in Default Setup workflow logs if a private package registry is configured using a GitHub Personal Access Token (PAT), but no username is configured. #3422
  • Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. #3421

4.32.0 - 26 Jan 2026

  • Update default CodeQL bundle version to 2.24.0. #3425

4.31.11 - 23 Jan 2026

  • When running a Default Setup workflow with Actions debugging enabled, the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. #3409
  • Improved error handling throughout the CodeQL Action. #3415
  • Added experimental support for automatically excluding generated files from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. #3318
  • The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. #3403

4.31.10 - 12 Jan 2026

  • Update default CodeQL bundle version to 2.23.9. #3393

4.31.9 - 16 Dec 2025

No user facing changes.

4.31.8 - 11 Dec 2025

... (truncated)

Commits
  • 89a39a4 Merge pull request #3494 from github/update-v4.32.4-39ba80c47
  • e5d84c8 Apply remaining review suggestions
  • 0c20209 Apply suggestions from code review
  • 314172e Fix typo
  • cdda72d Add changelog entries
  • cfda84c Update changelog for v4.32.4
  • 39ba80c Merge pull request #3493 from github/update-bundle/codeql-bundle-v2.24.2
  • 00150da Add changelog note
  • d97dce6 Update default bundle to codeql-bundle-v2.24.2
  • 50fdbb9 Merge pull request #3492 from github/henrymercer/new-repository-properties-ff
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.32.3&new-version=4.32.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 657e5d7b5f..8f06165fb3 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index c0b3af3eb5..1e00cfcfd9 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: sarif_file: "trivy-results.sarif" From ea0e6fd11afa3a2799c75d06411fff5ea106dd19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:52:31 -0500 Subject: [PATCH 223/448] deps: bump goreleaser/goreleaser-action from 6.4.0 to 7.0.0 (#2074) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 6.4.0 to 7.0.0.
Release notes

Sourced from goreleaser/goreleaser-action's releases.

v7.0.0

What's Changed

Full Changelog: https://github.com/goreleaser/goreleaser-action/compare/v6...v7.0.0

Commits
  • ec59f47 fix: yargs usage
  • 752dede fix: gitignore
  • 1881ae0 ci: update dependabot settings
  • fdc5e66 chore: gitignore provenance.json
  • 51b5b35 chore(deps): bump semver from 7.7.3 to 7.7.4 in the npm group (#539)
  • 4247c53 ci(deps): bump docker/setup-buildx-action in the actions group (#538)
  • c169bfd chore(deps): bump @​actions/http-client from 3.0.2 to 4.0.0 in the npm group (...
  • 902ab4a chore(deps): bump the npm group across 1 directory with 4 updates (#536)
  • c59a691 chore: gitignore
  • 56cc8b2 ci: add job to automate dependabot pre-checkin/vendor
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=goreleaser/goreleaser-action&package-manager=github_actions&previous-version=6.4.0&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 7caaa12e81..64ad60d3c7 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -29,7 +29,7 @@ jobs: with: go-version-file: go.mod - name: Run GoReleaser build - uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 + uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 env: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent with: @@ -51,7 +51,7 @@ jobs: with: go-version-file: go.mod - name: Run GoReleaser release - uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 + uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 with: distribution: goreleaser version: latest From 1936ab65f4d384cc6f2dd5fa4e6e47935709a78d Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Thu, 26 Feb 2026 07:18:39 +0000 Subject: [PATCH 224/448] feat(packetparser): add configurable BPF Ring Buffer support (#1981) # Description This PR introduces support for `BPF_MAP_TYPE_RINGBUF` in the `packetparser` plugin as a configurable alternative to `BPF_MAP_TYPE_PERF_EVENT_ARRAY`. Ring Buffers offer better performance and memory efficiency, especially on high-core systems, by using a shared buffer across CPUs rather than per-CPU buffers. ### Changes - **Configuration**: Added `packetParserRingBuffer` (enum: `enabled`/`disabled`; `auto` reserved) and `packetParserRingBufferSize` (uint32) to the Retina configuration and Helm charts. - **BPF**: Updated `packetparser.c` to conditionally compile with `BPF_MAP_TYPE_RINGBUF` when enabled. - **Userspace**: Updated `packetparser_linux.go` to: - Pass `-DUSE_RING_BUFFER` and `-DRING_BUFFER_SIZE` flags during BPF compilation. - Implement a `ringBufReaderWrapper` to adapt the `cilium/ebpf/ringbuf` reader to the existing reader interface. - Add logging to indicate which buffer type is active. - **Testing**: Updated unit tests to mock metrics correctly and added a new test case to verify compilation with Ring Buffer enabled. - **Userspace (follow-up)**: - Decoupled the reader interface from `cilium/ebpf/perf.Record` by introducing a custom `perfRecord` struct to support both perf array and ring buffer paths cleanly. - Added a `perfReaderWrapper` and updated `ringBufReaderWrapper` to convert records into the new `perfRecord` type. - **Kernel gating**: - Added shared kernel version parsing/comparison helpers and reusable kernel release retrieval utils. - Enforced a minimum kernel version when ring buffer mode is enabled. - Updated telemetry to reuse the shared kernel release helper. - **Docs/config**: Updated config docs and Helm `values.yaml` to reflect `packetParserRingBuffer`. - **Tests**: - Added unit tests for kernel release parsing and version comparison helpers. - Limited the ring buffer config test to Linux builds. - Adjusted packetparser tests to align with the new `perfRecord` reader interface. - **Chore/lint**: Addressed linting by using safe page-size casts, wrapping perf errors, and splitting long lines. ### Verification - Verified unit tests pass: `go test -v ./pkg/plugin/packetparser/...` - Manual verification on Kind: - Built image with `enablePacketParserRingBuffer: true`. - Deployed to Kind cluster. - Verified logs show "Initializing Ring Buffer reader". - Verified BPF map type is `ringbuf` using `bpftool`. ## Related Issues/PRs - #655 - fixes #1966 - #1965 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image Screenshot 2025-12-15 093850 Screenshot 2025-12-15 093819 ## Additional Notes Once this PR gets reviewed and merged, I will update the site docs accordingly. See issue #2016 In addition, I created an issue to implement an auto option to let retina decide at runtime whether to use `BPF_MAP_TYPE_RINGBUF` or not. See #2017 I stuck with `BPF_MAP_TYPE_PERF_EVENT_ARRAY` (Perf Buffers) as the default implementation because we still have a requirement to support Linux Kernel 5.4+, as noted in our [intro docs](https://retina.sh/docs/Introduction/intro). Since Ring Buffers (`BPF_MAP_TYPE_RINGBUF`) weren't introduced until kernel 5.8, making them the default would break Retina on older LTS environments (like Ubuntu 20.04) that we're currently committed to supporting. We also haven't had a chance to benchmark the performance difference on high-core clusters yet. The [upstream documentation](https://docs.ebpf.io/linux/map-type/BPF_MAP_TYPE_RINGBUF/) is clear that while `BPF_MAP_TYPE_RINGBUF` is generally more efficient, it uses a single shared ring buffer whereas `BPF_MAP_TYPE_PERF_EVENT_ARRAY` uses a per-CPU approach, which has different scalability characteristics. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Simone Rodigari --- .../retina/templates/agent/configmap.yaml | 2 + .../controller/helm/retina/values.yaml | 11 ++ .../helm/retina/templates/configmap.yaml | 2 + .../controller/helm/retina/values.yaml | 11 ++ docs/02-Installation/03-Config.md | 2 + docs/03-Metrics/plugins/Linux/packetparser.md | 6 +- pkg/config/config.go | 97 +++++++++-- pkg/config/config_test.go | 59 ++++++- pkg/config/testwith/config.yaml | 2 + pkg/plugin/conntrack/_cprog/dynamic.h | 3 +- pkg/plugin/packetparser/_cprog/packetparser.c | 16 ++ .../packetparser/packetparser_config_test.go | 89 ++++++++++ pkg/plugin/packetparser/packetparser_linux.go | 152 ++++++++++++++++-- .../packetparser/packetparser_linux_test.go | 110 ++++++++++--- pkg/plugin/packetparser/types_linux.go | 18 ++- pkg/telemetry/heartbeat_unix.go | 12 +- pkg/utils/kernel_release_unix.go | 38 +++++ pkg/utils/kernel_version_linux.go | 94 +++++++++++ pkg/utils/kernel_version_linux_test.go | 96 +++++++++++ test/profiles/advanced/values.yaml | 1 + 20 files changed, 764 insertions(+), 57 deletions(-) create mode 100644 pkg/plugin/packetparser/packetparser_config_test.go create mode 100644 pkg/utils/kernel_release_unix.go create mode 100644 pkg/utils/kernel_version_linux.go create mode 100644 pkg/utils/kernel_version_linux_test.go diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml index 0dd67890c4..6b1dd072a9 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml @@ -114,6 +114,8 @@ data: bypassLookupIPOfInterest: {{ .Values.bypassLookupIPOfInterest }} dataAggregationLevel: {{ .Values.dataAggregationLevel }} monitorSockPath: {{ .Values.monitorSockPath }} + packetParserRingBuffer: {{ .Values.packetParserRingBuffer }} + packetParserRingBufferSize: {{ .Values.packetParserRingBufferSize }} {{- end}} --- {{- if .Values.os.windows}} diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 998692b456..2e8b582ec8 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -68,6 +68,17 @@ enableAnnotations: false bypassLookupIPOfInterest: true dataAggregationLevel: "high" monitorSockPath: "/var/run/cilium/monitor1_2.sock" +# Use BPF ring buffers (BPF_MAP_TYPE_RINGBUF) instead of BPF_PERF_EVENT_ARRAY. +# Pros: lower per-event overhead at high event rates, simpler variable-sized records, more consistent latency. +# Cons: fixed-size pre-allocated (locked) memory that can be wasted on low traffic; events are dropped when the buffer fills (reserve fails). +# Possible values: "enabled", "disabled". +packetParserRingBuffer: "disabled" +# Ring buffer size in bytes (only used when packetParserRingBuffer="enabled"). +# Default: 8MiB (8388608). +# Valid range: power of two between the kernel page size and 1GiB (inclusive). +# Invalid values cause startup to fail with a validation error. +# This value is not applied when ring buffers are disabled. +packetParserRingBufferSize: 8388608 imagePullSecrets: [] nameOverride: "retina" diff --git a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml index 14f197b8eb..7de5ce98a3 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml @@ -26,6 +26,8 @@ data: dataAggregationLevel: {{ .Values.dataAggregationLevel }} telemetryInterval: {{ .Values.daemonset.telemetryInterval }} dataSamplingRate: {{ .Values.dataSamplingRate }} + packetParserRingBuffer: {{ .Values.packetParserRingBuffer }} + packetParserRingBufferSize: {{ .Values.packetParserRingBufferSize }} {{- end}} --- {{- if .Values.os.windows}} diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index 49902e33e4..8e2fbcb5e7 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -57,6 +57,17 @@ enableAnnotations: false bypassLookupIPOfInterest: false dataAggregationLevel: "low" dataSamplingRate: 1 +# Use BPF ring buffers (BPF_MAP_TYPE_RINGBUF) instead of BPF_PERF_EVENT_ARRAY. +# Pros: lower per-event overhead at high event rates, simpler variable-sized records, more consistent latency. +# Cons: fixed-size pre-allocated (locked) memory that can be wasted on low traffic; events are dropped when the buffer fills (reserve fails). +# Possible values: "enabled", "disabled". +packetParserRingBuffer: "disabled" +# Ring buffer size in bytes (only used when packetParserRingBuffer="enabled"). +# Default: 8MiB (8388608). +# Valid range: power of two between the kernel page size and 1GiB (inclusive). +# Invalid values cause startup to fail with a validation error. +# This value is not applied when ring buffers are disabled. +packetParserRingBufferSize: 8388608 imagePullSecrets: [] nameOverride: "retina" diff --git a/docs/02-Installation/03-Config.md b/docs/02-Installation/03-Config.md index 97dbac74d5..5c9422b206 100644 --- a/docs/02-Installation/03-Config.md +++ b/docs/02-Installation/03-Config.md @@ -54,6 +54,8 @@ Apply to both Agent and Operator. * `bypassLookupIPOfInterest`: If true, plugins like `packetparser` and `dropreason` will bypass IP lookup, generating an event for each packet regardless. `enableAnnotations` will not work if this is true. * `dataAggregationLevel`: Defines the level of data aggregation for Retina. See [Data Aggregation](../05-Concepts/data-aggregation.md) for more details. * `dataSamplingRate`: Defines the data sampling rate for `packetparser`. See [Sampling](../03-Metrics/plugins/Linux/packetparser.md#sampling) for more details. +* `packetParserRingBuffer`: Selects the kernel-to-userspace transport for `packetparser`. Accepted values: `enabled` (ring buffer) or `disabled` (perf event array). `auto` is reserved for future use. +* `packetParserRingBufferSize`: Ring buffer size in bytes when `packetParserRingBuffer=enabled`. Must be a power of two between the kernel page size and 1GiB (inclusive); invalid values cause startup to fail. ## Operator Configuration diff --git a/docs/03-Metrics/plugins/Linux/packetparser.md b/docs/03-Metrics/plugins/Linux/packetparser.md index e2a1621789..3585ccf977 100644 --- a/docs/03-Metrics/plugins/Linux/packetparser.md +++ b/docs/03-Metrics/plugins/Linux/packetparser.md @@ -27,7 +27,7 @@ A detailed analysis by a Retina user (see [this blog post](https://blog.zmalik.d **Current Implementation:** -The `packetparser` plugin currently uses **BPF_MAP_TYPE_PERF_EVENT_ARRAY** for kernel-to-userspace data transfer. This architecture creates per-CPU buffers that must be polled by a single reader thread. On systems with many CPU cores, this can lead to: +By default, `packetparser` uses **BPF_MAP_TYPE_PERF_EVENT_ARRAY** for kernel-to-userspace data transfer. This architecture creates per-CPU buffers that must be polled by a single reader thread. On systems with many CPU cores, this can lead to: - Increased context switching overhead - Memory access patterns that may not scale linearly @@ -35,7 +35,9 @@ The `packetparser` plugin currently uses **BPF_MAP_TYPE_PERF_EVENT_ARRAY** for k **Alternative Approaches:** -Alternative data transfer mechanisms like BPF ring buffers (BPF_MAP_TYPE_RINGBUF, available in Linux kernel 5.8+) use a shared buffer architecture that may perform better on high-core-count systems. However, **Retina does not currently support ring buffers for packetparser**. Future versions may provide configurable data transfer mechanisms. +Alternative data transfer mechanisms like BPF ring buffers (BPF_MAP_TYPE_RINGBUF, available in Linux kernel 5.8+) use a shared buffer architecture that may perform better on high-core-count systems. Retina supports ring buffers for `packetparser` via `packetParserRingBuffer=enabled` and `packetParserRingBufferSize`. + +**Note:** Ring buffer mode requires Linux kernel 5.8 or newer. #### If You Experience Performance Issues diff --git a/pkg/config/config.go b/pkg/config/config.go index f9086ff902..6c5fc5b307 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -3,6 +3,7 @@ package config import ( + "errors" "fmt" "log" "reflect" @@ -23,8 +24,27 @@ const ( High ) +type PacketParserRingBufferMode string + +const ( + PacketParserRingBufferDisabled PacketParserRingBufferMode = "disabled" + PacketParserRingBufferEnabled PacketParserRingBufferMode = "enabled" + PacketParserRingBufferAuto PacketParserRingBufferMode = "auto" +) + +var ( + ErrPacketParserRingBufferAutoNotSupported = errors.New("packetParserRingBuffer mode auto is not supported yet") + ErrPacketParserRingBufferInvalid = errors.New("packetParserRingBuffer must be set to enabled or disabled") + ErrPacketParserRingBufferInvalidBool = errors.New( + "packetParserRingBuffer must be enabled or disabled, got boolean", + ) +) + var ( - ErrorTelemetryIntervalTooSmall = fmt.Errorf("telemetryInterval smaller than %v is not allowed", MinTelemetryInterval) + ErrorTelemetryIntervalTooSmall = fmt.Errorf( + "telemetryInterval smaller than %v is not allowed", + MinTelemetryInterval, + ) DefaultTelemetryInterval = 15 * time.Minute DefaultSamplingRate uint32 = 1 ) @@ -54,6 +74,28 @@ func (l *Level) String() string { } } +func (m *PacketParserRingBufferMode) UnmarshalText(text []byte) error { + s := strings.ToLower(strings.TrimSpace(string(text))) + switch s { + case string(PacketParserRingBufferEnabled): + *m = PacketParserRingBufferEnabled + return nil + case string(PacketParserRingBufferDisabled): + *m = PacketParserRingBufferDisabled + return nil + case string(PacketParserRingBufferAuto): + return ErrPacketParserRingBufferAutoNotSupported + case "": + return ErrPacketParserRingBufferInvalid + default: + return fmt.Errorf("invalid packetParserRingBuffer %q: %w", s, ErrPacketParserRingBufferInvalid) + } +} + +func (m *PacketParserRingBufferMode) IsEnabled() bool { + return *m == PacketParserRingBufferEnabled +} + type Server struct { Host string `yaml:"host"` Port int `yaml:"port"` @@ -65,18 +107,20 @@ type Config struct { EnabledPlugin []string `yaml:"enabledPlugin"` MetricsInterval time.Duration `yaml:"metricsInterval"` // Deprecated: Use only MetricsInterval instead in the go code. - MetricsIntervalDuration time.Duration `yaml:"metricsIntervalDuration"` - EnableTelemetry bool `yaml:"enableTelemetry"` - EnableRetinaEndpoint bool `yaml:"enableRetinaEndpoint"` - EnablePodLevel bool `yaml:"enablePodLevel"` - EnableConntrackMetrics bool `yaml:"enableConntrackMetrics"` - RemoteContext bool `yaml:"remoteContext"` - EnableAnnotations bool `yaml:"enableAnnotations"` - BypassLookupIPOfInterest bool `yaml:"bypassLookupIPOfInterest"` - DataAggregationLevel Level `yaml:"dataAggregationLevel"` - MonitorSockPath string `yaml:"monitorSockPath"` - TelemetryInterval time.Duration `yaml:"telemetryInterval"` - DataSamplingRate uint32 `yaml:"dataSamplingRate"` + MetricsIntervalDuration time.Duration `yaml:"metricsIntervalDuration"` + EnableTelemetry bool `yaml:"enableTelemetry"` + EnableRetinaEndpoint bool `yaml:"enableRetinaEndpoint"` + EnablePodLevel bool `yaml:"enablePodLevel"` + EnableConntrackMetrics bool `yaml:"enableConntrackMetrics"` + RemoteContext bool `yaml:"remoteContext"` + EnableAnnotations bool `yaml:"enableAnnotations"` + BypassLookupIPOfInterest bool `yaml:"bypassLookupIPOfInterest"` + DataAggregationLevel Level `yaml:"dataAggregationLevel"` + MonitorSockPath string `yaml:"monitorSockPath"` + TelemetryInterval time.Duration `yaml:"telemetryInterval"` + DataSamplingRate uint32 `yaml:"dataSamplingRate"` + PacketParserRingBuffer PacketParserRingBufferMode `yaml:"packetParserRingBuffer"` + PacketParserRingBufferSize uint32 `yaml:"packetParserRingBufferSize"` } func GetConfig(cfgFilename string) (*Config, error) { @@ -102,6 +146,7 @@ func GetConfig(cfgFilename string) (*Config, error) { mapstructure.StringToTimeDurationHookFunc(), // default hook. mapstructure.StringToSliceHookFunc(","), // default hook. decodeLevelHook, + decodePacketParserRingBufferModeHook, )) err = viper.Unmarshal(&config, decoderConfigOption) @@ -130,6 +175,13 @@ func GetConfig(cfgFilename string) (*Config, error) { config.DataSamplingRate = DefaultSamplingRate } + switch config.PacketParserRingBuffer { //nolint:exhaustive // we only care about Auto and empty (default) here + case "": + config.PacketParserRingBuffer = PacketParserRingBufferDisabled + case PacketParserRingBufferAuto: + return nil, ErrPacketParserRingBufferAutoNotSupported + } + return &config, nil } @@ -149,3 +201,22 @@ func decodeLevelHook(field, target reflect.Type, data interface{}) (interface{}, } return level, nil } + +func decodePacketParserRingBufferModeHook(field, target reflect.Type, data interface{}) (interface{}, error) { + if target != reflect.TypeOf(PacketParserRingBufferMode("")) { + return data, nil + } + + switch field.Kind() { //nolint:exhaustive // we only care about String and Bool + case reflect.String: + var mode PacketParserRingBufferMode + if err := mode.UnmarshalText([]byte(data.(string))); err != nil { + return nil, err + } + return mode, nil + case reflect.Bool: + return nil, ErrPacketParserRingBufferInvalidBool + default: + return data, nil + } +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index d26d6e5835..7b899e3524 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -29,7 +29,8 @@ func TestGetConfig(t *testing.T) { c.EnableAnnotations || c.TelemetryInterval != 15*time.Minute || c.DataAggregationLevel != Low || - c.DataSamplingRate != 1 { + c.DataSamplingRate != 1 || + c.PacketParserRingBuffer != PacketParserRingBufferDisabled { t.Errorf("Expeted config should be same as ./testwith/config.yaml; instead got %+v", c) } } @@ -68,3 +69,59 @@ func TestDecodeLevelHook(t *testing.T) { assert.Equal(t, test.expected, result) } } + +func TestDecodePacketParserRingBufferModeHook(t *testing.T) { + tests := []struct { + name string + input interface{} + expected interface{} + expectErr bool + expectedError error + }{ + { + name: "enabled", + input: "enabled", + expected: PacketParserRingBufferEnabled, + }, + { + name: "disabled", + input: "disabled", + expected: PacketParserRingBufferDisabled, + }, + { + name: "auto not supported", + input: "auto", + expectErr: true, + expectedError: ErrPacketParserRingBufferAutoNotSupported, + }, + { + name: "boolean rejected", + input: true, + expectErr: true, + }, + { + name: "non-string passthrough", + input: 123, + expected: 123, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result, err := decodePacketParserRingBufferModeHook( + reflect.TypeOf(test.input), + reflect.TypeOf(PacketParserRingBufferMode("")), + test.input, + ) + if test.expectErr { + require.Error(t, err) + if test.expectedError != nil { + require.ErrorIs(t, err, test.expectedError) + } + return + } + require.NoError(t, err) + assert.Equal(t, test.expected, result) + }) + } +} diff --git a/pkg/config/testwith/config.yaml b/pkg/config/testwith/config.yaml index edcb5d685a..ff8dc0fb4d 100644 --- a/pkg/config/testwith/config.yaml +++ b/pkg/config/testwith/config.yaml @@ -10,3 +10,5 @@ metricsIntervalDuration: "10s" telemetryEnabled: true dataAggregationLevel: "low" telemetryInterval: "15m" +packetParserRingBuffer: "disabled" +packetParserRingBufferSize: 8388608 diff --git a/pkg/plugin/conntrack/_cprog/dynamic.h b/pkg/plugin/conntrack/_cprog/dynamic.h index 80abbd931f..76e9c73f6b 100644 --- a/pkg/plugin/conntrack/_cprog/dynamic.h +++ b/pkg/plugin/conntrack/_cprog/dynamic.h @@ -1,2 +1 @@ -// Place holder header file that will be replaced by the actual header file during runtime -// DO NOT DELETE +#define ENABLE_CONNTRACK_METRICS 1 diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c index d961c81f5c..5d63edde0a 100644 --- a/pkg/plugin/packetparser/_cprog/packetparser.c +++ b/pkg/plugin/packetparser/_cprog/packetparser.c @@ -16,8 +16,16 @@ char __license[] SEC("license") = "Dual MIT/GPL"; struct { +#ifdef USE_RING_BUFFER + __uint(type, BPF_MAP_TYPE_RINGBUF); +#ifndef RING_BUFFER_SIZE +#define RING_BUFFER_SIZE (8 * 1024 * 1024) +#endif + __uint(max_entries, RING_BUFFER_SIZE); +#else __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(max_entries, 16384); +#endif } retina_packetparser_events SEC(".maps"); // Define const variables to avoid warnings. @@ -231,7 +239,11 @@ static void parse(struct __sk_buff *skb, __u8 obs) p.previously_observed_packets = 0; p.previously_observed_bytes = 0; __builtin_memset(&p.previously_observed_flags, 0, sizeof(struct tcpflagscount)); +#ifdef USE_RING_BUFFER + bpf_ringbuf_output(&retina_packetparser_events, &p, sizeof(p), 0); +#else bpf_perf_event_output(skb, &retina_packetparser_events, BPF_F_CURRENT_CPU, &p, sizeof(p)); +#endif return; // If the data aggregation level is high, only send the packet to the perf buffer if it needs to be reported. #elif DATA_AGGREGATION_LEVEL == DATA_AGGREGATION_LEVEL_HIGH @@ -239,7 +251,11 @@ static void parse(struct __sk_buff *skb, __u8 obs) p.previously_observed_packets = report.previously_observed_packets; p.previously_observed_bytes = report.previously_observed_bytes; p.previously_observed_flags = report.previously_observed_flags; +#ifdef USE_RING_BUFFER + bpf_ringbuf_output(&retina_packetparser_events, &p, sizeof(p), 0); +#else bpf_perf_event_output(skb, &retina_packetparser_events, BPF_F_CURRENT_CPU, &p, sizeof(p)); +#endif } #endif #endif diff --git a/pkg/plugin/packetparser/packetparser_config_test.go b/pkg/plugin/packetparser/packetparser_config_test.go new file mode 100644 index 0000000000..0f8ea27587 --- /dev/null +++ b/pkg/plugin/packetparser/packetparser_config_test.go @@ -0,0 +1,89 @@ +//go:build linux +// +build linux + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package packetparser + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestValidateRingBufferSize(t *testing.T) { + const maxSize = 1 * 1024 * 1024 * 1024 // 1GB + intPageSize := os.Getpagesize() + if intPageSize <= 0 { + intPageSize = 4096 + } + if intPageSize > int(^uint32(0)) { + intPageSize = int(^uint32(0)) + } + //nolint:gosec // bounded to uint32 + pageSize := uint32(intPageSize) + + tests := []struct { + name string + inputSize uint32 + expectedErr bool + expectedMsg string + }{ + { + name: "Zero input returns error", + inputSize: 0, + expectedErr: true, + expectedMsg: "must be set", + }, + { + name: "Below page size returns error", + inputSize: pageSize - 1, + expectedErr: true, + expectedMsg: "page size", + }, + { + name: "Above max size returns error", + inputSize: maxSize + 1, + expectedErr: true, + expectedMsg: "maximum", + }, + { + name: "Not power of 2 returns error", + inputSize: (8 * 1024 * 1024) + 1, + expectedErr: true, + expectedMsg: "power of 2", + }, + { + name: "Valid size returns no error", + inputSize: 16 * 1024 * 1024, + expectedErr: false, + }, + { + name: "Valid max size returns no error", + inputSize: maxSize, + expectedErr: false, + }, + { + name: "Valid page size returns no error (assuming page size is power of 2)", + inputSize: pageSize, + expectedErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validateRingBufferSize(tt.inputSize) + if tt.expectedErr { + require.Error(t, err) + if tt.expectedMsg != "" { + assert.Contains(t, err.Error(), tt.expectedMsg) + } + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index b89773699d..85c53b2241 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -21,6 +21,7 @@ import ( v1 "github.com/cilium/cilium/pkg/hubble/api/v1" "github.com/cilium/ebpf" "github.com/cilium/ebpf/perf" + "github.com/cilium/ebpf/ringbuf" tc "github.com/florianl/go-tc" helper "github.com/florianl/go-tc/core" nl "github.com/mdlayher/netlink" @@ -51,7 +52,14 @@ import ( ) //go:generate go run github.com/cilium/ebpf/cmd/bpf2go@master -cflags "-g -O2 -Wall -D__TARGET_ARCH_${GOARCH} -Wall" -target ${GOARCH} -type packet packetparser ./_cprog/packetparser.c -- -I../lib/_${GOARCH} -I../lib/common/libbpf/_src -I../lib/common/libbpf/_include/linux -I../lib/common/libbpf/_include/uapi/linux -I../lib/common/libbpf/_include/asm -I../filter/_cprog/ -I../conntrack/_cprog/ -var errNoOutgoingLinks = errors.New("could not determine any outgoing links") +var ( + errNoOutgoingLinks = errors.New("could not determine any outgoing links") + errRingBufKernelTooOld = errors.New("ring buffer requires newer kernel") + errRingBufSizeUnset = errors.New("ring buffer size must be set when ring buffers are enabled") + errRingBufSizeTooSmall = errors.New("ring buffer size is smaller than the kernel page size") + errRingBufSizeTooLarge = errors.New("ring buffer size is larger than the allowed maximum") + errRingBufSizeNotPowerOfTwo = errors.New("ring buffer size is not a power of 2") +) func init() { registry.Add(name, New) @@ -130,6 +138,36 @@ func (p *packetParser) Generate(ctx context.Context) error { return nil } +// validateRingBufferSize validates the ring buffer size and returns an error for invalid values. +func validateRingBufferSize(size uint32) error { + const maxSize = 1 * 1024 * 1024 * 1024 // 1GB + intPageSize := os.Getpagesize() + if intPageSize <= 0 { + intPageSize = 4096 + } + if intPageSize > int(^uint32(0)) { + intPageSize = int(^uint32(0)) + } + //nolint:gosec // bounded to uint32 + pageSize := uint32(intPageSize) + + if size == 0 { + return errRingBufSizeUnset + } + if size < pageSize { + return fmt.Errorf("%w: size=%d page_size=%d", errRingBufSizeTooSmall, size, pageSize) + } + if size > maxSize { + return fmt.Errorf("%w: size=%d max_size=%d", errRingBufSizeTooLarge, size, maxSize) + } + // Check if size is a power of 2. + if (size & (size - 1)) != 0 { + return fmt.Errorf("%w: size=%d", errRingBufSizeNotPowerOfTwo, size) + } + + return nil +} + func (p *packetParser) Compile(ctx context.Context) error { // Get the absolute path to this file during runtime. dir, err := absPath() @@ -152,7 +190,8 @@ func (p *packetParser) Compile(ctx context.Context) error { targetArch = "-D__TARGET_ARCH_arm64" } // Keep target as bpf, otherwise clang compilation yields bpf object that elf reader cannot load. - err = loader.CompileEbpf(ctx, "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, "-o", bpfOutputFile, + cflags := []string{ + "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, "-o", bpfOutputFile, archLibDir, libbpfSrcDir, libbpfIncludeAsmDir, @@ -160,7 +199,21 @@ func (p *packetParser) Compile(ctx context.Context) error { libbpfIncludeUapiLinuxDir, filterDir, conntrackDir, - ) + } + + if p.cfg.PacketParserRingBuffer.IsEnabled() { + if validateErr := validateRingBufferSize(p.cfg.PacketParserRingBufferSize); validateErr != nil { + return validateErr + } + + p.l.Info("Compiling with Ring Buffer enabled", zap.Uint32("size", p.cfg.PacketParserRingBufferSize)) + cflags = append(cflags, + "-DUSE_RING_BUFFER", + fmt.Sprintf("-DRING_BUFFER_SIZE=%d", p.cfg.PacketParserRingBufferSize), + ) + } + + err = loader.CompileEbpf(ctx, cflags...) if err != nil { return err } @@ -174,6 +227,11 @@ func (p *packetParser) Init() error { p.l.Warn("packet parser and latency plugin will not init because pod level is disabled") return nil } + if p.cfg.PacketParserRingBuffer.IsEnabled() { + if ringBufErr := ensureRingBufKernelSupported(); ringBufErr != nil { + return ringBufErr + } + } // Get the absolute path to this file during runtime. dir, err := absPath() if err != nil { @@ -222,10 +280,24 @@ func (p *packetParser) Init() error { return err } - p.reader, err = plugincommon.NewPerfReader(p.l, objs.RetinaPacketparserEvents, perCPUBuffer, 1) - if err != nil { - p.l.Error("Error NewReader", zap.Error(err)) - return err + if p.cfg.PacketParserRingBuffer.IsEnabled() { + p.l.Info("Initializing Ring Buffer reader") + var rb *ringbuf.Reader + rb, err = ringbuf.NewReader(objs.RetinaPacketparserEvents) + if err != nil { + p.l.Error("Error NewReader ringbuf", zap.Error(err)) + return fmt.Errorf("failed to create ringbuf reader: %w", err) + } + p.reader = &ringBufReaderWrapper{reader: rb} + } else { + p.l.Info("Initializing Perf Reader") + var pr *perf.Reader + pr, err = plugincommon.NewPerfReader(p.l, objs.RetinaPacketparserEvents, perCPUBuffer, 1) + if err != nil { + p.l.Error("Error NewReader", zap.Error(err)) + return fmt.Errorf("failed to create perf reader: %w", err) + } + p.reader = &perfReaderWrapper{reader: pr} } p.tcMap = &sync.Map{} @@ -284,7 +356,7 @@ func (p *packetParser) Start(ctx context.Context) error { } // Create the channel. - p.recordsChannel = make(chan perf.Record, buffer) + p.recordsChannel = make(chan perfRecord, buffer) p.l.Debug("Created records channel") return p.run(ctx) @@ -696,7 +768,7 @@ func (p *packetParser) readData() { // This is unblocked by the close call. record, err := p.reader.Read() if err != nil { - if errors.Is(err, perf.ErrClosed) { + if errors.Is(err, perf.ErrClosed) || errors.Is(err, ringbuf.ErrClosed) { p.l.Error("Perf array is empty") // nothing to do, we're done } else { @@ -731,3 +803,65 @@ func absPath() (string, error) { dir := path.Dir(filename) return dir, nil } + +type ringBufReaderWrapper struct { + reader *ringbuf.Reader +} + +func (r *ringBufReaderWrapper) Read() (perfRecord, error) { + rec, err := r.reader.Read() + if err != nil { + return perfRecord{}, fmt.Errorf("failed to read from ringbuf: %w", err) + } + return perfRecord{ + RawSample: rec.RawSample, + Remaining: rec.Remaining, + }, nil +} + +func (r *ringBufReaderWrapper) Close() error { + if err := r.reader.Close(); err != nil { + return fmt.Errorf("failed to close ringbuf reader: %w", err) + } + return nil +} + +type perfReaderWrapper struct { + reader *perf.Reader +} + +func (r *perfReaderWrapper) Read() (perfRecord, error) { + rec, err := r.reader.Read() + if err != nil { + return perfRecord{}, fmt.Errorf("failed to read perf record: %w", err) + } + return perfRecord{ + CPU: rec.CPU, + LostSamples: rec.LostSamples, + RawSample: rec.RawSample, + }, nil +} + +func (r *perfReaderWrapper) Close() error { + if err := r.reader.Close(); err != nil { + return fmt.Errorf("failed to close perf reader: %w", err) + } + return nil +} + +func ensureRingBufKernelSupported() error { + kv, err := utils.LinuxKernelVersion() + if err != nil { + return fmt.Errorf("failed to detect kernel version for ring buffer support: %w", err) + } + + if !kv.AtLeast(ringBufMinKernelMajor, ringBufMinKernelMinor, ringBufMinKernelPatch) { + return fmt.Errorf( + "%w: requires >= %d.%d.%d, current: %s", + errRingBufKernelTooOld, + ringBufMinKernelMajor, ringBufMinKernelMinor, ringBufMinKernelPatch, kv.Release, + ) + } + + return nil +} diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go index 0d32b8fcf6..4fa8b86aa0 100644 --- a/pkg/plugin/packetparser/packetparser_linux_test.go +++ b/pkg/plugin/packetparser/packetparser_linux_test.go @@ -33,6 +33,30 @@ import ( "go.uber.org/mock/gomock" ) +type perfReaderAdapter struct { + mock *mocks.MockperfReader +} + +func (p *perfReaderAdapter) Read() (perfRecord, error) { + rec, err := p.mock.Read() + if err != nil { + return perfRecord{}, fmt.Errorf("failed to read perf record: %w", err) + } + return perfRecord{ + CPU: rec.CPU, + LostSamples: rec.LostSamples, + RawSample: rec.RawSample, + Remaining: rec.Remaining, + }, nil +} + +func (p *perfReaderAdapter) Close() error { + if err := p.mock.Close(); err != nil { + return fmt.Errorf("failed to close perf reader: %w", err) + } + return nil +} + var ( cfgPodLevelEnabled = &kcfg.Config{ EnablePodLevel: true, @@ -56,6 +80,11 @@ var ( BypassLookupIPOfInterest: true, EnableConntrackMetrics: true, } + cfgRingBufferEnabled = &kcfg.Config{ + EnablePodLevel: true, + PacketParserRingBuffer: kcfg.PacketParserRingBufferEnabled, + PacketParserRingBufferSize: 4096, + } ) func TestCleanAll(t *testing.T) { @@ -295,7 +324,7 @@ func TestReadData_Error(t *testing.T) { p := &packetParser{ cfg: cfgPodLevelEnabled, l: log.Logger().Named("test"), - reader: mperf, + reader: &perfReaderAdapter{mock: mperf}, } p.readData() @@ -334,9 +363,9 @@ func TestReadDataPodLevelEnabled(t *testing.T) { p := &packetParser{ cfg: cfgPodLevelEnabled, l: log.Logger().Named("test"), - reader: mperf, + reader: &perfReaderAdapter{mock: mperf}, enricher: menricher, - recordsChannel: make(chan perf.Record, buffer), + recordsChannel: make(chan perfRecord, buffer), } mICounterVec := metrics.NewMockCounterVec(ctrl) @@ -345,7 +374,8 @@ func TestReadDataPodLevelEnabled(t *testing.T) { metrics.LostEventsCounter = mICounterVec mParsedPacketsCounter := metrics.NewMockCounterVec(ctrl) - mParsedPacketsCounter.EXPECT().WithLabelValues(gomock.Any()).Return(prometheus.NewCounter(prometheus.CounterOpts{})).AnyTimes() + mParsedPacketsCounter.EXPECT().WithLabelValues(gomock.Any()). + Return(prometheus.NewCounter(prometheus.CounterOpts{})).AnyTimes() metrics.ParsedPacketsCounter = mParsedPacketsCounter exCh := make(chan *v1.Event, 10) @@ -431,8 +461,8 @@ func TestStartWithDataAggregationLevelLow(t *testing.T) { cfg: cfgDataAggregationLevelLow, l: log.Logger().Named("test"), objs: pObj, - reader: mockReader, - recordsChannel: make(chan perf.Record, buffer), + reader: &perfReaderAdapter{mock: mockReader}, + recordsChannel: make(chan perfRecord, buffer), interfaceLockMap: &sync.Map{}, endpointIngressInfo: &ebpf.ProgramInfo{ Name: "ingress", @@ -510,8 +540,8 @@ func TestStartWithDataAggregationLevelHigh(t *testing.T) { cfg: cfgDataAggregationLevelHigh, l: log.Logger().Named("test"), objs: pObj, - reader: mockReader, - recordsChannel: make(chan perf.Record, buffer), + reader: &perfReaderAdapter{mock: mockReader}, + recordsChannel: make(chan perfRecord, buffer), interfaceLockMap: &sync.Map{}, endpointIngressInfo: &ebpf.ProgramInfo{ Name: "ingress", @@ -562,24 +592,33 @@ func TestPacketParseGenerate(t *testing.T) { expectedContents string }{ { - name: "PodLevelEnabled", - cfg: cfgPodLevelEnabled, - expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n#define DATA_SAMPLING_RATE 0\n", + name: "PodLevelEnabled", + cfg: cfgPodLevelEnabled, + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n" + + "#define DATA_AGGREGATION_LEVEL 0\n" + + "#define DATA_SAMPLING_RATE 0\n", }, { - name: "ConntrackMetricsEnabled", - cfg: cfgConntrackMetricsEnabled, - expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define ENABLE_CONNTRACK_METRICS 1\n#define DATA_AGGREGATION_LEVEL 1\n#define DATA_SAMPLING_RATE 0\n", + name: "ConntrackMetricsEnabled", + cfg: cfgConntrackMetricsEnabled, + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n" + + "#define ENABLE_CONNTRACK_METRICS 1\n" + + "#define DATA_AGGREGATION_LEVEL 1\n" + + "#define DATA_SAMPLING_RATE 0\n", }, { - name: "DataAggregationLevelLow", - cfg: cfgDataAggregationLevelLow, - expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n#define DATA_AGGREGATION_LEVEL 0\n#define DATA_SAMPLING_RATE 0\n", + name: "DataAggregationLevelLow", + cfg: cfgDataAggregationLevelLow, + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n" + + "#define DATA_AGGREGATION_LEVEL 0\n" + + "#define DATA_SAMPLING_RATE 0\n", }, { - name: "DataAggregationLevelHigh", - cfg: cfgDataAggregationLevelHigh, - expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n#define DATA_AGGREGATION_LEVEL 1\n#define DATA_SAMPLING_RATE 0\n", + name: "DataAggregationLevelHigh", + cfg: cfgDataAggregationLevelHigh, + expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n" + + "#define DATA_AGGREGATION_LEVEL 1\n" + + "#define DATA_SAMPLING_RATE 0\n", }, } @@ -644,6 +683,37 @@ func TestCompile(t *testing.T) { } } +func TestCompileRingBuffer(t *testing.T) { + takeBackup() + defer restoreBackup() + + log.SetupZapLogger(log.GetDefaultLogOpts()) //nolint:errcheck // ignore + p := &packetParser{ + cfg: cfgRingBufferEnabled, + l: log.Logger().Named(name), + } + dir, _ := absPath() + expectedOutputFile := fmt.Sprintf("%s/%s", dir, bpfObjectFileName) + + err := os.Remove(expectedOutputFile) + if err != nil && !errors.Is(err, os.ErrNotExist) { + t.Fatalf("Expected no error. Error: %+v", err) + } + + err = p.Generate(context.Background()) + if err != nil { + t.Fatalf("Expected no error. Error: %+v", err) + } + + err = p.Compile(context.Background()) + if err != nil { + t.Fatalf("Expected no error. Error: %+v", err) + } + if _, err := os.Stat(expectedOutputFile); errors.Is(err, os.ErrNotExist) { + t.Fatalf("File %+v doesn't exist", expectedOutputFile) + } +} + // Helpers. func takeBackup() { // Get the directory of the current test file. diff --git a/pkg/plugin/packetparser/types_linux.go b/pkg/plugin/packetparser/types_linux.go index 7f1e1abe25..a968b910ad 100644 --- a/pkg/plugin/packetparser/types_linux.go +++ b/pkg/plugin/packetparser/types_linux.go @@ -10,7 +10,6 @@ import ( v1 "github.com/cilium/cilium/pkg/hubble/api/v1" "github.com/cilium/ebpf" - "github.com/cilium/ebpf/perf" tc "github.com/florianl/go-tc" nl "github.com/mdlayher/netlink" "github.com/vishvananda/netlink" @@ -51,6 +50,12 @@ const ( Device interfaceType = "device" ) +const ( + ringBufMinKernelMajor = 5 + ringBufMinKernelMinor = 8 + ringBufMinKernelPatch = 0 +) + var ( getQdisc = func(tcnl nltc) qdisc { return tcnl.Qdisc() @@ -102,10 +107,17 @@ type nltc interface { } type perfReader interface { - Read() (perf.Record, error) + Read() (perfRecord, error) Close() error } +type perfRecord struct { + CPU int + LostSamples uint64 + RawSample []byte + Remaining int +} + type packetParser struct { cfg *kcfg.Config l *log.ZapLogger @@ -122,7 +134,7 @@ type packetParser struct { hostIngressInfo *ebpf.ProgramInfo hostEgressInfo *ebpf.ProgramInfo wg sync.WaitGroup - recordsChannel chan perf.Record + recordsChannel chan perfRecord externalChannel chan *v1.Event } diff --git a/pkg/telemetry/heartbeat_unix.go b/pkg/telemetry/heartbeat_unix.go index dc20736099..ae725cabb1 100644 --- a/pkg/telemetry/heartbeat_unix.go +++ b/pkg/telemetry/heartbeat_unix.go @@ -7,17 +7,15 @@ package telemetry import ( "context" - "os/exec" - "strings" + "github.com/microsoft/retina/pkg/utils" "github.com/pkg/errors" ) -func KernelVersion(ctx context.Context) (string, error) { - cmd := exec.CommandContext(ctx, "uname", "-r") - output, err := cmd.CombinedOutput() +func KernelVersion(context.Context) (string, error) { + release, err := utils.KernelRelease() if err != nil { - return "", errors.Wrapf(err, "failed to get linux kernel version: %s", string(output)) + return "", errors.Wrap(err, "failed to get linux kernel version") } - return strings.TrimSuffix(string(output), "\n"), nil + return release, nil } diff --git a/pkg/utils/kernel_release_unix.go b/pkg/utils/kernel_release_unix.go new file mode 100644 index 0000000000..c3d09bc70b --- /dev/null +++ b/pkg/utils/kernel_release_unix.go @@ -0,0 +1,38 @@ +//go:build unix + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//revive:disable:var-naming +package utils + +//revive:enable:var-naming + +import ( + "fmt" + + "golang.org/x/sys/unix" +) + +// KernelRelease returns the kernel release string (e.g. "5.15.0-101-generic"). +func KernelRelease() (string, error) { + var uts unix.Utsname + if err := unix.Uname(&uts); err != nil { + return "", fmt.Errorf("uname failed: %w", err) + } + return charsToString(uts.Release[:]), nil +} + +func charsToString(ca []byte) string { + n := 0 + for ; n < len(ca); n++ { + if ca[n] == 0 { + break + } + } + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = ca[i] + } + return string(b) +} diff --git a/pkg/utils/kernel_version_linux.go b/pkg/utils/kernel_version_linux.go new file mode 100644 index 0000000000..7fd2a71d7f --- /dev/null +++ b/pkg/utils/kernel_version_linux.go @@ -0,0 +1,94 @@ +//go:build linux + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//revive:disable:var-naming +package utils + +//revive:enable:var-naming + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "golang.org/x/mod/semver" +) + +// KernelVersion represents a parsed Linux kernel version. +type KernelVersion struct { + Major int + Minor int + Patch int + Release string +} + +var ( + errUnexpectedKernelReleaseFormat = errors.New("unexpected kernel release format") + errInvalidKernelSemver = errors.New("invalid kernel semver") +) + +// LinuxKernelVersion returns the parsed Linux kernel version and release string. +func LinuxKernelVersion() (KernelVersion, error) { + release, err := KernelRelease() + if err != nil { + return KernelVersion{}, err + } + major, minor, patch, err := ParseLinuxKernelRelease(release) + if err != nil { + return KernelVersion{Release: release}, err + } + return KernelVersion{Major: major, Minor: minor, Patch: patch, Release: release}, nil +} + +// AtLeast reports whether the kernel version is >= the required version. +func (v KernelVersion) AtLeast(major, minor, patch int) bool { + current := kernelSemverFromParts(v.Major, v.Minor, v.Patch) + required := kernelSemverFromParts(major, minor, patch) + return semver.Compare(current, required) >= 0 +} + +// ParseLinuxKernelRelease parses the uname release string into semantic version parts. +func ParseLinuxKernelRelease(release string) (major, minor, patch int, err error) { + _, major, minor, patch, err = normalizeKernelReleaseToSemver(release) + if err != nil { + return 0, 0, 0, err + } + return major, minor, patch, nil +} + +func kernelSemverFromParts(major, minor, patch int) string { + return fmt.Sprintf("v%d.%d.%d", major, minor, patch) +} + +func normalizeKernelReleaseToSemver(release string) (version string, major, minor, patch int, err error) { + base := strings.SplitN(release, "-", 2)[0] + parts := strings.Split(base, ".") + if len(parts) < 2 { + return "", 0, 0, 0, fmt.Errorf("%w: %q", errUnexpectedKernelReleaseFormat, release) + } + + major, err = strconv.Atoi(parts[0]) + if err != nil { + return "", 0, 0, 0, fmt.Errorf("invalid kernel major in %q: %w", release, err) + } + minor, err = strconv.Atoi(parts[1]) + if err != nil { + return "", 0, 0, 0, fmt.Errorf("invalid kernel minor in %q: %w", release, err) + } + patch = 0 + if len(parts) >= 3 { + if patch, err = strconv.Atoi(parts[2]); err != nil { + return "", 0, 0, 0, fmt.Errorf("invalid kernel patch in %q: %w", release, err) + } + } + + version = kernelSemverFromParts(major, minor, patch) + if !semver.IsValid(version) { + return "", 0, 0, 0, fmt.Errorf("%w for %q: %s", errInvalidKernelSemver, release, version) + } + + return version, major, minor, patch, nil +} diff --git a/pkg/utils/kernel_version_linux_test.go b/pkg/utils/kernel_version_linux_test.go new file mode 100644 index 0000000000..28dde47df7 --- /dev/null +++ b/pkg/utils/kernel_version_linux_test.go @@ -0,0 +1,96 @@ +//go:build linux + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//revive:disable-next-line:var-naming +package utils + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseLinuxKernelRelease(t *testing.T) { + tests := []struct { + name string + release string + expectMajor int + expectMinor int + expectPatch int + expectErr bool + }{ + { + name: "full version with suffix", + release: "5.15.0-101-generic", + expectMajor: 5, + expectMinor: 15, + expectPatch: 0, + expectErr: false, + }, + { + name: "no patch version", + release: "6.1-foo", + expectMajor: 6, + expectMinor: 1, + expectPatch: 0, + expectErr: false, + }, + { + name: "full numeric version", + release: "4.19.260", + expectMajor: 4, + expectMinor: 19, + expectPatch: 260, + expectErr: false, + }, + { + name: "extra numeric segment", + release: "5.15.153.1-microsoft-standard-WSL2", + expectMajor: 5, + expectMinor: 15, + expectPatch: 153, + expectErr: false, + }, + { + name: "invalid format", + release: "foo", + expectErr: true, + }, + { + name: "invalid minor", + release: "5.x.1", + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + major, minor, patch, err := ParseLinuxKernelRelease(tt.release) + if tt.expectErr { + assert.Error(t, err) + return + } + require.NoError(t, err) + assert.Equal(t, tt.expectMajor, major) + assert.Equal(t, tt.expectMinor, minor) + assert.Equal(t, tt.expectPatch, patch) + }) + } +} + +func TestKernelVersionAtLeast(t *testing.T) { + v := KernelVersion{Major: 5, Minor: 8, Patch: 0} + + assert.True(t, v.AtLeast(5, 8, 0)) + assert.True(t, v.AtLeast(5, 7, 99)) + assert.False(t, v.AtLeast(5, 8, 1)) + assert.False(t, v.AtLeast(6, 0, 0)) + + v2 := KernelVersion{Major: 6, Minor: 1, Patch: 3} + assert.True(t, v2.AtLeast(5, 8, 0)) + assert.True(t, v2.AtLeast(6, 1, 3)) + assert.False(t, v2.AtLeast(6, 2, 0)) +} diff --git a/test/profiles/advanced/values.yaml b/test/profiles/advanced/values.yaml index 6025ce3539..5c07e6eaaf 100644 --- a/test/profiles/advanced/values.yaml +++ b/test/profiles/advanced/values.yaml @@ -1,5 +1,6 @@ enablePodLevel: true enableAnnotations: true +packetParserRingBuffer: "enabled" operator: enabled: true enableRetinaEndpoint: true From 8272d3d2de83f36ce07c0a08194461e9c7e7208c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:50:05 -0500 Subject: [PATCH 225/448] deps: bump actions/setup-go from 6.2.0 to 6.3.0 (#2080) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.2.0 to 6.3.0.
Release notes

Sourced from actions/setup-go's releases.

v6.3.0

What's Changed

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.3.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=6.2.0&new-version=6.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 12 ++++++------ .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-images.yaml | 10 +++++----- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 8f06165fb3..f47cc147fa 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -36,7 +36,7 @@ jobs: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - name: Initialize CodeQL diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index fb0be2dafc..df038209df 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -90,7 +90,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index d9ed7ab093..e5390ae721 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - name: golangci-lint diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 64ad60d3c7..8975a64699 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - name: Run GoReleaser build @@ -47,7 +47,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - name: Run GoReleaser release diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 52fc7c9a9f..29cf36c74f 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -48,7 +48,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -91,7 +91,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -193,7 +193,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -246,7 +246,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -298,7 +298,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -383,7 +383,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index e383d86a41..f9bf10aa32 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -52,7 +52,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 5b55e82e4d..634972c7f5 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -32,7 +32,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -70,7 +70,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -162,7 +162,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -210,7 +210,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version @@ -256,7 +256,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index e50409ae9c..34c0891556 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -72,7 +72,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index ca1f15368a..0dd6fac1fb 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 71a6a10f4f..7aae87a41a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -25,7 +25,7 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod From 2341ace1acc37458e8270eb59ac37669ea9b5f4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:52:19 +0000 Subject: [PATCH 226/448] deps: bump aquasecurity/trivy-action from 0.34.0 to 0.34.1 (#2071) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.34.0 to 0.34.1.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.34.1

What's Changed

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.34.0...0.34.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.34.0&new-version=0.34.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 1e00cfcfd9..2045100e85 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -39,7 +39,7 @@ jobs: echo "TAG=$TAG" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@c1824fd6edce30d7ab345a9989de00bbd46ef284 # 0.34.0 + uses: aquasecurity/trivy-action@e368e328979b113139d6f9068e03accaed98a518 # 0.34.1 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From 9594703135f12903ea1952778cf4a28e71faa90b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:40:23 -0500 Subject: [PATCH 227/448] deps: bump rajatjindal/krew-release-bot from 0.0.47 to 0.0.50 (#2073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [rajatjindal/krew-release-bot](https://github.com/rajatjindal/krew-release-bot) from 0.0.47 to 0.0.50.
Release notes

Sourced from rajatjindal/krew-release-bot's releases.

v0.0.50

What's Changed

Full Changelog: https://github.com/rajatjindal/krew-release-bot/compare/v0.0.49...v0.0.50

Release v0.0.49

What's Changed

Full Changelog: https://github.com/rajatjindal/krew-release-bot/compare/v0.0.48...v0.0.49

Release v0.0.48

What's Changed

New Contributors

Full Changelog: https://github.com/rajatjindal/krew-release-bot/compare/v0.0.47...v0.0.48

Commits
  • a7e82ae fix(goreleaser): also test goreleaser in CI (#86)
  • c0984d3 update golang and actions version (#85)
  • ecba13d fix(action): use latest tagged image version (#84)
  • e2d6f27 chore(make): add test target (#82)
  • 8d76bf0 chore(git): ignore .idea paraphernalia (#81)
  • 35e214f fix(netlify): vendor dir is no longer used
  • ccdd6b1 chore(netlify): update go version requested for build in netlify
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rajatjindal/krew-release-bot&package-manager=github_actions&previous-version=0.0.47&new-version=0.0.50)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 8975a64699..8899bc66a5 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -61,4 +61,4 @@ jobs: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent - name: Update new version in krew-index if: github.repository_owner == 'microsoft' - uses: rajatjindal/krew-release-bot@3d9faef30a82761d610544f62afddca00993eef9 # v0.0.47 + uses: rajatjindal/krew-release-bot@a7e82ae57ca41a16fca2691ef00e8a8d35bc77d4 # v0.0.50 From b35fd8c77928b2c3af9aae05a98e4837834da636 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 27 Feb 2026 04:52:44 -0500 Subject: [PATCH 228/448] fix(ci): install syft in goreleaser workflow for SBOM generation (#2081) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The goreleaser workflow fails at the SBOM cataloging step because `syft` is not installed on the runner. `.goreleaser.yaml` declares `sboms: [artifacts: archive]` which requires Syft, but the workflow never installs it. This was surfaced by the [v1.1.0 release run](https://github.com/microsoft/retina/actions/runs/22452857876): ``` ⨯ release failed after 9m34s error=exec: "syft": executable file not found in $PATH ``` Add `anchore/sbom-action/download-syft@v0.23.0` (pinned to SHA) to both the `build` and `release` jobs. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI workflow change — will be validated by the next tag push or PR build. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- .github/workflows/goreleaser.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 8899bc66a5..6518e406a6 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -28,6 +28,8 @@ jobs: uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod + - name: Install Syft + uses: anchore/sbom-action/download-syft@17ae1740179002c89186b61233e0f892c3118b11 # v0.23.0 - name: Run GoReleaser build uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 env: @@ -50,6 +52,8 @@ jobs: uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod + - name: Install Syft + uses: anchore/sbom-action/download-syft@17ae1740179002c89186b61233e0f892c3118b11 # v0.23.0 - name: Run GoReleaser release uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 with: From dd0fd15a2876678211d4bc6efbeecaa9ebaa8392 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 22:22:46 -0500 Subject: [PATCH 229/448] deps: bump actions/upload-artifact from 6.0.0 to 7.0.0 (#2083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
Release notes

Sourced from actions/upload-artifact's releases.

v7.0.0

v7 What's new

Direct Uploads

Adds support for uploading single files directly (unzipped). Callers can set the new archive parameter to false to skip zipping the file during upload. Right now, we only support single files. The action will fail if the glob passed resolves to multiple files. The name parameter is also ignored with this setting. Instead, the name of the artifact will be the name of the uploaded file.

ESM

To support new versions of the @actions/* packages, we've upgraded the package to ESM.

What's Changed

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v6...v7.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=6.0.0&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- .github/workflows/test.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 29cf36c74f..aa91491ffa 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -110,7 +110,7 @@ jobs: APP_INSIGHTS_ID: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} - name: Upload Windows Binaries - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 634972c7f5..7b4af14f8e 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -86,7 +86,7 @@ jobs: TAG=$TAG - name: Upload Windows Binaries - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7aae87a41a..716c4423e5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -37,7 +37,7 @@ jobs: make test-image IMAGE_NAMESPACE=${{ github.repository }} PLATFORM=linux/amd64 - name: Upload Artifacts - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: coverage-files path: ./artifacts/coverage* From b30accb4206774dd366590e9c1441bf528a3aa5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 00:18:23 -0500 Subject: [PATCH 230/448] deps: bump actions/download-artifact from 7.0.0 to 8.0.0 (#2082) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0.
Release notes

Sourced from actions/download-artifact's releases.

v8.0.0

v8 - What's new

Direct downloads

To support direct uploads in actions/upload-artifact, the action will no longer attempt to unzip all downloaded files. Instead, the action checks the Content-Type header ahead of unzipping and skips non-zipped files. Callers wishing to download a zipped file as-is can also set the new skip-decompress parameter to false.

Enforced checks (breaking)

A previous release introduced digest checks on the download. If a download hash didn't match the expected hash from the server, the action would log a warning. Callers can now configure the behavior on mismatch with the digest-mismatch parameter. To be secure by default, we are now defaulting the behavior to error which will fail the workflow run.

ESM

To support new versions of the @actions/* packages, we've upgraded the package to ESM.

What's Changed

Full Changelog: https://github.com/actions/download-artifact/compare/v7...v8.0.0

Commits
  • 70fc10c Merge pull request #461 from actions/danwkennedy/digest-mismatch-behavior
  • f258da9 Add change docs
  • ccc058e Fix linting issues
  • bd7976b Add a setting to specify what to do on hash mismatch and default it to error
  • ac21fcf Merge pull request #460 from actions/danwkennedy/download-no-unzip
  • 15999bf Add note about package bumps
  • 974686e Bump the version to v8 and add release notes
  • fbe48b1 Update test names to make it clearer what they do
  • 96bf374 One more test fix
  • b8c4819 Fix skip decompress test
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=7.0.0&new-version=8.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index aa91491ffa..c25ebf39c0 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -133,7 +133,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 7b4af14f8e..b0e72362b3 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -109,7 +109,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: windows-binaries path: output/windows_amd64/ From c1622e099f6859ef53e3cdbb115f618e6a0fbd55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 00:57:49 -0500 Subject: [PATCH 231/448] deps: bump github/codeql-action from 4.32.4 to 4.32.5 (#2087) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.4 to 4.32.5.
Release notes

Sourced from github/codeql-action's releases.

v4.32.5

  • Repositories owned by an organization can now set up the github-codeql-disable-overlay custom repository property to disable improved incremental analysis for CodeQL. First, create a custom repository property with the name github-codeql-disable-overlay and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to true to disable improved incremental analysis. For more information, see Managing custom properties for repositories in your organization. This feature is not yet available on GitHub Enterprise Server. #3507
  • Added an experimental change so that when improved incremental analysis fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. #3487
  • The minimum memory check for improved incremental analysis is now skipped for CodeQL 2.24.3 and later, which has reduced peak RAM usage. #3515
  • Reduced log levels for best-effort private package registry connection check failures to reduce noise from workflow annotations. #3516
  • Added an experimental change which lowers the minimum disk space requirement for improved incremental analysis, enabling it to run on standard GitHub Actions runners. We expect to roll this change out to everyone in March. #3498
  • Added an experimental change which allows the start-proxy action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. #3512
  • The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. #3503, #3504
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.32.5 - 02 Mar 2026

  • Repositories owned by an organization can now set up the github-codeql-disable-overlay custom repository property to disable improved incremental analysis for CodeQL. First, create a custom repository property with the name github-codeql-disable-overlay and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to true to disable improved incremental analysis. For more information, see Managing custom properties for repositories in your organization. This feature is not yet available on GitHub Enterprise Server. #3507
  • Added an experimental change so that when improved incremental analysis fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. #3487
  • The minimum memory check for improved incremental analysis is now skipped for CodeQL 2.24.3 and later, which has reduced peak RAM usage. #3515
  • Reduced log levels for best-effort private package registry connection check failures to reduce noise from workflow annotations. #3516
  • Added an experimental change which lowers the minimum disk space requirement for improved incremental analysis, enabling it to run on standard GitHub Actions runners. We expect to roll this change out to everyone in March. #3498
  • Added an experimental change which allows the start-proxy action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. #3512
  • The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. #3503, #3504

4.32.4 - 20 Feb 2026

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473
  • When the CodeQL Action is run with debugging enabled in Default Setup and private package registries are configured, the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. #3486
  • Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. #3485
  • Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a nightly CodeQL CLI release instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. #3484

4.32.3 - 13 Feb 2026

  • Added experimental support for testing connections to private package registries. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. #3466

4.32.2 - 05 Feb 2026

  • Update default CodeQL bundle version to 2.24.1. #3460

4.32.1 - 02 Feb 2026

  • A warning is now shown in Default Setup workflow logs if a private package registry is configured using a GitHub Personal Access Token (PAT), but no username is configured. #3422
  • Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. #3421

4.32.0 - 26 Jan 2026

  • Update default CodeQL bundle version to 2.24.0. #3425

4.31.11 - 23 Jan 2026

  • When running a Default Setup workflow with Actions debugging enabled, the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. #3409
  • Improved error handling throughout the CodeQL Action. #3415
  • Added experimental support for automatically excluding generated files from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. #3318
  • The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. #3403

... (truncated)

Commits
  • c793b71 Merge pull request #3523 from github/update-v4.32.5-ca42bf226
  • 06cd615 Soften language re overlay failures
  • f5516c6 Improve changelog
  • 97519e1 Update release date
  • 05259a1 Add more changelog notes
  • 01ee2f7 Add changelog notes
  • c72d9a4 Update changelog for v4.32.5
  • ca42bf2 Merge pull request #3522 from github/henrymercer/update-supported-versions-table
  • 6704d80 Merge pull request #3520 from github/dependabot/npm_and_yarn/fast-xml-parser-...
  • 76348c0 Merge pull request #3521 from github/dependabot/npm_and_yarn/minimatch-3.1.5
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.32.4&new-version=4.32.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index f47cc147fa..56b97490b2 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 2045100e85..e181992714 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: sarif_file: "trivy-results.sarif" From c6c4d5398c191d2f3a6493c7a7b69a5bd035a97d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:47:33 -0500 Subject: [PATCH 232/448] chore(deps): bump minimatch from 3.1.2 to 3.1.5 in /site in the npm_and_yarn group across 1 directory (#2091) Bumps the npm_and_yarn group with 1 update in the /site directory: [minimatch](https://github.com/isaacs/minimatch). Updates `minimatch` from 3.1.2 to 3.1.5
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=minimatch&package-manager=npm_and_yarn&previous-version=3.1.2&new-version=3.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 92409f9f92..6dafbd2bff 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -13499,9 +13499,10 @@ "license": "ISC" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -17136,15 +17137,15 @@ } }, "node_modules/serve-handler": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", - "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.7.tgz", + "integrity": "sha512-CinAq1xWb0vR3twAv9evEU8cNWkXCb9kd5ePAHUKJBkOsUpR1wt/CvGdeca7vqumL1U5cSaeVQ6zZMxiJ3yWsg==", "license": "MIT", "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "mime-types": "2.1.18", - "minimatch": "3.1.2", + "minimatch": "3.1.5", "path-is-inside": "1.0.2", "path-to-regexp": "3.3.0", "range-parser": "1.2.0" From 7de4b88142f7e96ef135ee58a3b7223dacb50fb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:47:57 -0500 Subject: [PATCH 233/448] deps: bump actions/setup-node from 6.2.0 to 6.3.0 (#2092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.2.0 to 6.3.0.
Release notes

Sourced from actions/setup-node's releases.

v6.3.0

What's Changed

Enhancements:

When using node-version-file: package.json, setup-node now prefers devEngines.runtime over engines.node.

Dependency updates:

Bug fixes:

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v6...v6.3.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=6.2.0&new-version=6.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index c81a8b6cfb..ff1100b6aa 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 20 - name: build From cc745099c1922048a825e418e76c3c33ac2195ee Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 4 Mar 2026 12:55:19 -0500 Subject: [PATCH 234/448] chore(deps): bump Go to 1.26.0 and update all Docker base images (#2059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Bump Go to 1.26.0 and all Docker base images to their latest versions. This makes Retina FIPS-ready. ### What changed - **Go**: 1.24.11 → 1.26.0 (azurelinux, windowsservercore, and plain variants) - **AzureLinux base images**: `base/core:3.0` and `distroless/minimal:3.0` to latest digests - **Windows base images**: `nanoserver` and `servercore` for ltsc2022 to latest digests - **CLI Dockerfile**: use `azurelinux-core` libs stage instead of copying from the full Go SDK image - Copy OpenSSL config (`/etc/pki/tls/`) into distroless images for FIPS support ### Go 1.26.0 migration notes Microsoft Go 1.26.0 enables `GOEXPERIMENT=systemcrypto` by default, which routes all crypto operations through the system's OpenSSL library via CGO. This requires: - **`CGO_ENABLED=1`** (removed all `CGO_ENABLED=0` from Dockerfiles) - **Shared libraries** (`/lib/`, `/usr/lib/`) copied into distroless final images for dynamic linking at runtime - **OpenSSL config** (`/etc/pki/tls/`) copied into distroless images so OpenSSL discovers the SymCrypt FIPS provider ### FIPS readiness The images are FIPS-ready and can be activated at deploy time by setting `GOFIPS=1`: - Binaries are built with `microsoft_systemcrypto=1`, routing crypto through OpenSSL - AzureLinux ships SymCrypt (`libsymcrypt.so`) as its FIPS 140-3 validated module - The `symcryptprovider.so` OpenSSL provider and `openssl.cnf` config are included ### Image size impact (linux/amd64) Compared against published v1.0.4 images: ```bash docker image inspect --format '{{.Size}}' | awk '{printf "%.1f MB\n", $1/1024/1024}' ``` | Image | v1.0.4 | This PR | Delta | |-------|--------|---------|-------| | retina-agent | 691.5 MB | 692.5 MB | +0.9 MB (+0.1%) | | retina-init | 369.6 MB | 370.2 MB | +0.5 MB (+0.1%) | | retina-operator | 334.9 MB | 333.2 MB | -1.6 MB (-0.4%) | | kubectl-retina | 82.0 MB | 146.7 MB | +64.7 MB (+79%) | The `kubectl-retina` increase is expected — it was previously a static binary (`CGO_ENABLED=0`, 82 MB) and is now dynamically linked (108 MB binary + 42 MB system libraries) for FIPS/OpenSSL support. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed - Built all Linux amd64 images locally and verified image sizes - `kubectl-retina version` and `kubectl-retina --help` work correctly in the distroless image - Verified dynamically linked binary resolves all shared libraries from the `azurelinux-core` libs stage ## Additional Notes 16 Dockerfiles updated across controller, operator, cli, shell, test, and hack/tools directories. Signed-off-by: Quang Nguyen --- cli/Dockerfile | 20 +++++++++++++------ controller/Dockerfile | 12 ++++++----- controller/Dockerfile.gogen | 6 +++--- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-2022 | 2 +- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 6 +++--- .../Dockerfile.windows-retina-oss-build | 2 +- hack/tools/kapinger/Dockerfile | 16 ++++++++++----- hack/tools/toolbox/Dockerfile | 5 +++-- operator/Dockerfile | 7 ++++--- operator/Dockerfile.windows-2022 | 6 +++--- shell/Dockerfile | 2 +- test/image/Dockerfile | 6 +++--- 14 files changed, 58 insertions(+), 40 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index b13122dcd5..5c924385e0 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -16,21 +16,29 @@ ARG GOARCH=amd64 ENV GOARCH=${GOARCH} RUN --mount=type=cache,target="/root/.cache/go-build" \ - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ + go build \ -ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" \ -X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID" \ -X "github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName"="$AGENT_IMAGE_NAME"" \ -a -o kubectl-retina cli/main.go +# minimal libs stage — provides only the system libraries needed by the CGO-enabled binary, +# without the bloat of the full Go SDK image (python, gcc, systemd, etc.) +# skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 AS libs + # Target 1: Distroless (secure, minimal) # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS distroless-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba AS distroless-target +COPY --from=libs /lib/ /lib +COPY --from=libs /usr/lib/ /usr/lib +COPY --from=libs /etc/pki/tls/ /etc/pki/tls/ WORKDIR / COPY --from=builder /workspace/kubectl-retina . # Target 2: Shell-enabled (operational, init container support) -# skopeo inspect docker://mcr.microsoft.com/cbl-mariner/base/core:2.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/cbl-mariner/base/core@sha256:4d97d662d71c1fda938ed9df36d8f490d9107cff37e89c0efa932d073285ad85 AS shell-target +# skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 AS shell-target WORKDIR / COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina RUN chmod +x /bin/kubectl-retina diff --git a/controller/Dockerfile b/controller/Dockerfile index 534e91765b..d6b958140c 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,13 +1,13 @@ # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS azurelinux-distroless +FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba AS azurelinux-distroless # build stages @@ -101,14 +101,16 @@ FROM azurelinux-distroless AS init COPY --from=init-bin /go/bin/retina/initretina /retina/initretina COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib +COPY --from=tools /etc/pki/tls/ /etc/pki/tls/ ENTRYPOINT ["./retina/initretina"] # agent final image # mcr.microsoft.com/azurelinux/distroless/minimal:3.0 -# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c +# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba FROM azurelinux-distroless AS agent COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib +COPY --from=tools /etc/pki/tls/ /etc/pki/tls/ COPY --from=tools /tmp/bin/ /bin COPY --from=controller-bin /go/bin/retina/controller /retina/controller COPY --from=controller-bin /go/src/github.com/microsoft/retina/pkg/plugin /go/src/github.com/microsoft/retina/pkg/plugin diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 198ad63ed4..d07bbe0e3d 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef # Default linux/architecture. ARG GOOS=linux @@ -24,4 +24,4 @@ RUN ln -s /usr/bin/clang-14 /usr/bin/clang WORKDIR /app # Generate go code. -ENTRYPOINT mkdir /tmp/.cache && export GOCACHE=/tmp/.cache && CGO_ENABLED=0 go generate ./... +ENTRYPOINT mkdir /tmp/.cache && export GOCACHE=/tmp/.cache && go generate ./... diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 2eca3baa35..e7055c7f5d 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 555ecf1e71..3767bbb20d 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,6 +1,6 @@ # pinned base image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS ltsc2022 FROM ltsc2022 AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 8e6c83ea3c..b2315c52a6 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:2ab8d921bd819de69bddf5ac78c7e117055492eb36a2fed0c93851514a4587d8 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:179ddfa34eda50f58ea0011202f559585ade9668a298fe81ac01cebdc9bef15c AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index f1794dfbe0..14af6943b3 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:2ab8d921bd819de69bddf5ac78c7e117055492eb36a2fed0c93851514a4587d8 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:179ddfa34eda50f58ea0011202f559585ade9668a298fe81ac01cebdc9bef15c AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:643adf84ee2338ee4811fd891adb9e912917dc6c0ca85399982e1bebda4f2295 AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:60612a30303eb5a15ce7f53fa2eecf70bca41d72657de0482fbde601ae5f3403 AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index 8a1f5be288..c98ffe727a 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -3,7 +3,7 @@ ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:3750d7fcd320130cc2ce61954902b71729e85ec2c07c5a2e83a6d6c7f34a61e5 AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 141e36db9e..22be839b4b 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,30 +1,36 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.24.11 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:66a04c4bcea1fafc935246c96af236eb4d91d501387e061ae59f134c8993dae9 AS builder WORKDIR /build ADD . . RUN go mod download # Build for Linux -RUN CGO_ENABLED=0 GOOS=linux go build -o kapinger . +RUN GOOS=linux go build -o kapinger . # Build for Windows -RUN CGO_ENABLED=0 GOOS=windows go build -o kapinger.exe . +RUN GOOS=windows go build -o kapinger.exe . # Build for ARM64 Linux -RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o kapinger-arm64 . +RUN GOOS=linux GOARCH=arm64 go build -o kapinger-arm64 . FROM --platform=linux/amd64 scratch AS linux-amd64 +COPY --from=builder /lib/ /lib +COPY --from=builder /usr/lib/ /usr/lib WORKDIR /app COPY --from=builder /build/kapinger . CMD ["./kapinger"] -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore:ltsc2022 AS windows-amd64 +# skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS windows-amd64 WORKDIR /app COPY --from=builder /build/kapinger.exe . ENTRYPOINT [ "cmd.exe" ] CMD [ "/c", "kapinger.exe" ] FROM --platform=linux/arm64 scratch AS linux-arm64 +COPY --from=builder /lib/ /lib +COPY --from=builder /usr/lib/ /usr/lib WORKDIR /app COPY --from=builder /build/kapinger-arm64 . CMD ["./kapinger-arm64"] diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 6afb47f4a8..475de1a33e 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,7 +1,8 @@ -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.24.11 AS build +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:66a04c4bcea1fafc935246c96af236eb4d91d501387e061ae59f134c8993dae9 AS build ADD . . WORKDIR /go/toolbox/ -RUN CGO_ENABLED=0 GOOS=linux go build -o server . +RUN GOOS=linux go build -o server . FROM mcr.microsoft.com/mirror/docker/library/ubuntu:24.04 RUN apt-get update diff --git a/operator/Dockerfile b/operator/Dockerfile index 6b42ca0940..a6e34f5037 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,10 +25,11 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ ##################### controller ####################### # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib +COPY --from=builder /etc/pki/tls/ /etc/pki/tls/ COPY --from=builder /workspace/retina-operator . USER 65532:65532 diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index a4b3113006..0b47c88f7a 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder # Build args ARG VERSION @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:643adf84ee2338ee4811fd891adb9e912917dc6c0ca85399982e1bebda4f2295 +FROM mcr.microsoft.com/windows/nanoserver@sha256:60612a30303eb5a15ce7f53fa2eecf70bca41d72657de0482fbde601ae5f3403 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/shell/Dockerfile b/shell/Dockerfile index 2654eed0aa..86f6605055 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d +FROM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 RUN tdnf install -y \ bind-utils \ diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 9516478daf..f9552e56e4 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,7 +1,7 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder -ENV CGO_ENABLED=0 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder +ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina RUN tdnf install -y clang lld bpftool libbpf-devel make git jq From 0b990f7a18a470d12132d61ec5b757ef1acbd5b2 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 4 Mar 2026 14:29:00 -0500 Subject: [PATCH 235/448] fix(utils): handle '+' suffix in kernel version parsing (#2090) ## Description Currently `normalizeKernelReleaseToSemver` only strips `-` suffixes from the uname release string before parsing version components. GKE Container-Optimized OS uses kernel versions like `6.6.113+`, which causes `strconv.Atoi` to fail on the patch component (`"113+"`). This PR strips `+` suffixes from the base version string before splitting into parts, matching how `+` is used as a build metadata separator in semver. ## Related Issue Fixes #2086 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ```bash go test -tags=unit ./pkg/utils/ -run TestParseLinuxKernelRelease -v ``` All 8 test cases pass, including two new cases for `6.6.113+` and `6.6.113+gke-12345`. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- pkg/utils/kernel_version_linux.go | 1 + pkg/utils/kernel_version_linux_test.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/pkg/utils/kernel_version_linux.go b/pkg/utils/kernel_version_linux.go index 7fd2a71d7f..2f415e315e 100644 --- a/pkg/utils/kernel_version_linux.go +++ b/pkg/utils/kernel_version_linux.go @@ -65,6 +65,7 @@ func kernelSemverFromParts(major, minor, patch int) string { func normalizeKernelReleaseToSemver(release string) (version string, major, minor, patch int, err error) { base := strings.SplitN(release, "-", 2)[0] + base = strings.SplitN(base, "+", 2)[0] parts := strings.Split(base, ".") if len(parts) < 2 { return "", 0, 0, 0, fmt.Errorf("%w: %q", errUnexpectedKernelReleaseFormat, release) diff --git a/pkg/utils/kernel_version_linux_test.go b/pkg/utils/kernel_version_linux_test.go index 28dde47df7..f1619734e8 100644 --- a/pkg/utils/kernel_version_linux_test.go +++ b/pkg/utils/kernel_version_linux_test.go @@ -54,6 +54,22 @@ func TestParseLinuxKernelRelease(t *testing.T) { expectPatch: 153, expectErr: false, }, + { + name: "plus suffix (GKE Container-Optimized OS)", + release: "6.6.113+", + expectMajor: 6, + expectMinor: 6, + expectPatch: 113, + expectErr: false, + }, + { + name: "plus suffix with build metadata", + release: "6.6.113+gke-12345", + expectMajor: 6, + expectMinor: 6, + expectPatch: 113, + expectErr: false, + }, { name: "invalid format", release: "foo", From 3cd74e60dd238c6b581c5f338128c79ad6675e44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 14:29:21 -0500 Subject: [PATCH 236/448] deps: bump docker/setup-qemu-action from 3.7.0 to 4.0.0 (#2093) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.7.0 to 4.0.0.
Release notes

Sourced from docker/setup-qemu-action's releases.

v4.0.0

Full Changelog: https://github.com/docker/setup-qemu-action/compare/v3.7.0...v4.0.0

Commits
  • ce36039 Merge pull request #245 from crazy-max/node24
  • 6386344 node 24 as default runtime
  • 1ea3db7 Merge pull request #243 from docker/dependabot/npm_and_yarn/docker/actions-to...
  • b56a002 chore: update generated content
  • c43f02d build(deps): bump @​docker/actions-toolkit from 0.67.0 to 0.77.0
  • ce10c58 Merge pull request #244 from docker/dependabot/npm_and_yarn/actions/core-3.0.0
  • 429fc9d chore: update generated content
  • 060e5f8 build(deps): bump @​actions/core from 1.11.1 to 3.0.0
  • 44be13e Merge pull request #231 from docker/dependabot/npm_and_yarn/js-yaml-3.14.2
  • 1897438 chore: update generated content
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/setup-qemu-action&package-manager=github_actions&previous-version=3.7.0&new-version=4.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index c25ebf39c0..cc9577ecf2 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -354,7 +354,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Azure CLI login uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index b0e72362b3..b40ddeef90 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -305,7 +305,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Install Cosign uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 From 34517b00cc8fe127a01ce2e3a77e72fa04d8f667 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:23:44 -0500 Subject: [PATCH 237/448] deps: bump aquasecurity/trivy-action from 0.34.1 to 0.34.2 (#2088) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.34.1 to 0.34.2.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.34.2

What's Changed

New Contributors

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.34.1...0.34.2

Commits
  • 97e0b38 chore: bump Trivy version to v0.69.2 in test workflow and README (#515)
  • 4c61e63 chore: bump default Trivy version to v0.69.2 (#513)
  • 1bd0625 Merge pull request #508 from nikpivkin/feat/pass-yaml-ignore-file
  • bce3086 remove unused init-cache target
  • 5a9fbb1 supress progress bar when download db
  • 1615450 update trivyignores input description
  • df85774 add comment about fd3
  • 56c8dae remove unused variable
  • 6476b93 feat: support for YAML ignore file
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.34.1&new-version=0.34.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index e181992714..c8672169ff 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -39,7 +39,7 @@ jobs: echo "TAG=$TAG" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@e368e328979b113139d6f9068e03accaed98a518 # 0.34.1 + uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 # 0.34.2 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From c9e49019badbae72b0396f3cfd644d60660c3495 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 17:04:54 -0500 Subject: [PATCH 238/448] deps: bump rajatjindal/krew-release-bot from 0.0.50 to 0.0.51 (#2089) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [rajatjindal/krew-release-bot](https://github.com/rajatjindal/krew-release-bot) from 0.0.50 to 0.0.51.
Release notes

Sourced from rajatjindal/krew-release-bot's releases.

v0.0.51

What's Changed

Full Changelog: https://github.com/rajatjindal/krew-release-bot/compare/v0.0.50...v0.0.51

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rajatjindal/krew-release-bot&package-manager=github_actions&previous-version=0.0.50&new-version=0.0.51)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 6518e406a6..6ea2f7ca11 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -65,4 +65,4 @@ jobs: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent - name: Update new version in krew-index if: github.repository_owner == 'microsoft' - uses: rajatjindal/krew-release-bot@a7e82ae57ca41a16fca2691ef00e8a8d35bc77d4 # v0.0.50 + uses: rajatjindal/krew-release-bot@c970b8a8f6dbc2f2285a26e3ae160903b87002c3 # v0.0.51 From bacb9cdc96bf49408ac33274c545e2f18d5d5669 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:16:25 -0500 Subject: [PATCH 239/448] deps: bump docker/setup-buildx-action from 3 to 4 (#2095) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
Release notes

Sourced from docker/setup-buildx-action's releases.

v4.0.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.12.0...v4.0.0

v3.12.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.11.1...v3.12.0

v3.11.1

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.11.0...v3.11.1

v3.11.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.10.0...v3.11.0

v3.10.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.9.0...v3.10.0

v3.9.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.8.0...v3.9.0

v3.8.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v3.7.1...v3.8.0

... (truncated)

Commits
  • 4d04d5d Merge pull request #485 from docker/dependabot/npm_and_yarn/docker/actions-to...
  • cd74e05 chore: update generated content
  • eee38ec build(deps): bump @​docker/actions-toolkit from 0.77.0 to 0.79.0
  • 7a83f65 Merge pull request #484 from docker/dependabot/github_actions/docker/setup-qe...
  • a5aa967 Merge pull request #464 from crazy-max/rm-deprecated
  • e73d53f build(deps): bump docker/setup-qemu-action from 3 to 4
  • 28a438e Merge pull request #483 from crazy-max/node24
  • 034e9d3 chore: update generated content
  • b4664d8 remove deprecated inputs/outputs
  • a8257de node 24 as default runtime
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/setup-buildx-action&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/kapinger.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 964d4df20b..02069b0a61 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -20,7 +20,7 @@ jobs: run: echo ${{ steps.vars.outputs.sha_short }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 # - name: Login to GitHub Container Registry # uses: docker/login-action@v1 From 1645646df582cfad12859d06f73211a2141c3217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 10:08:10 -0500 Subject: [PATCH 240/448] chore(deps): bump svgo from 3.3.2 to 3.3.3 in /site in the npm_and_yarn group across 1 directory (#2099) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 1 update in the /site directory: [svgo](https://github.com/svg/svgo). Updates `svgo` from 3.3.2 to 3.3.3
Release notes

Sourced from svgo's releases.

v3.3.3

What's Changed

Dependencies

  • Migrates from our unsupported fork of sax (@​trysound/sax) to the upstream version of sax (sax).

Bug Fixes

  • No longer throws error when encountering comments in DTD.

Metrics

Before and after of the browser bundle of each respective version:

v3.3.2 v3.3.3 Delta
svgo.browser.js 910.9 kB 912.9 kB ⬆️ 2 kB

Support

SVGO v3 is not officially supported, please consider upgrading to SVGO v4 instead. We've backported this fix as there are security implications, but there is no commitment to do this for more complex changes in future.

Consider reading our Migration Guide from v3 to v4 which should ease the process.

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=svgo&package-manager=npm_and_yarn&previous-version=3.3.2&new-version=3.3.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 6dafbd2bff..45f5abfbb0 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -5238,15 +5238,6 @@ "node": ">=14.16" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "license": "ISC", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@types/body-parser": { "version": "1.19.6", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", @@ -16964,9 +16955,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -17905,18 +17896,18 @@ "license": "MIT" }, "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", "license": "MIT", "dependencies": { - "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", - "picocolors": "^1.0.0" + "picocolors": "^1.0.0", + "sax": "^1.5.0" }, "bin": { "svgo": "bin/svgo" From 732952a83edaafe5dfbf6e02278f86a5e4481141 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:18:44 +0000 Subject: [PATCH 241/448] deps: bump github/codeql-action from 4.32.5 to 4.32.6 (#2102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.5 to 4.32.6.
Release notes

Sourced from github/codeql-action's releases.

v4.32.6

  • Update default CodeQL bundle version to 2.24.3. #3548
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.32.6 - 05 Mar 2026

  • Update default CodeQL bundle version to 2.24.3. #3548

4.32.5 - 02 Mar 2026

  • Repositories owned by an organization can now set up the github-codeql-disable-overlay custom repository property to disable improved incremental analysis for CodeQL. First, create a custom repository property with the name github-codeql-disable-overlay and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to true to disable improved incremental analysis. For more information, see Managing custom properties for repositories in your organization. This feature is not yet available on GitHub Enterprise Server. #3507
  • Added an experimental change so that when improved incremental analysis fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. #3487
  • The minimum memory check for improved incremental analysis is now skipped for CodeQL 2.24.3 and later, which has reduced peak RAM usage. #3515
  • Reduced log levels for best-effort private package registry connection check failures to reduce noise from workflow annotations. #3516
  • Added an experimental change which lowers the minimum disk space requirement for improved incremental analysis, enabling it to run on standard GitHub Actions runners. We expect to roll this change out to everyone in March. #3498
  • Added an experimental change which allows the start-proxy action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. #3512
  • The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. #3503, #3504

4.32.4 - 20 Feb 2026

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473
  • When the CodeQL Action is run with debugging enabled in Default Setup and private package registries are configured, the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. #3486
  • Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. #3485
  • Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a nightly CodeQL CLI release instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. #3484

4.32.3 - 13 Feb 2026

  • Added experimental support for testing connections to private package registries. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. #3466

4.32.2 - 05 Feb 2026

  • Update default CodeQL bundle version to 2.24.1. #3460

4.32.1 - 02 Feb 2026

  • A warning is now shown in Default Setup workflow logs if a private package registry is configured using a GitHub Personal Access Token (PAT), but no username is configured. #3422
  • Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. #3421

4.32.0 - 26 Jan 2026

  • Update default CodeQL bundle version to 2.24.0. #3425

4.31.11 - 23 Jan 2026

  • When running a Default Setup workflow with Actions debugging enabled, the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. #3409

... (truncated)

Commits
  • 0d579ff Merge pull request #3551 from github/update-v4.32.6-72d2d850d
  • d4c6be7 Update changelog for v4.32.6
  • 72d2d85 Merge pull request #3548 from github/update-bundle/codeql-bundle-v2.24.3
  • 23f983c Merge pull request #3544 from github/dependabot/github_actions/dot-github/wor...
  • 832e97c Merge pull request #3545 from github/dependabot/github_actions/dot-github/wor...
  • 5ef38c0 Merge pull request #3546 from github/dependabot/npm_and_yarn/tar-7.5.10
  • 80c9cda Add changelog note
  • f2669dd Update default bundle to codeql-bundle-v2.24.3
  • bd03c44 Merge branch 'main' into dependabot/github_actions/dot-github/workflows/actio...
  • 102d762 Bump tar from 7.5.7 to 7.5.10
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.32.5&new-version=4.32.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 56b97490b2..109b502f2a 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index c8672169ff..9b87f38c09 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: sarif_file: "trivy-results.sarif" From 13ca7804021aa3589c151f1f6a5a3c7dc8c2dfbd Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 13 Mar 2026 17:41:12 -0400 Subject: [PATCH 242/448] chore: improve devcontainer experience (#2097) ## Description The devcontainer is missing several tools needed for development (LLVM/clang, jq), uses a shell script for setup instead of declarative devcontainer features, and has no CI validation. This PR overhauls the devcontainer: - Replace `installMoreTools.sh` with declarative devcontainer features (LLVM 17, pinned versions) - Add persistent Go module/build cache volume mounts - Add jq, Kind cluster auto-creation on startup, and VS Code settings for golangci-lint + gofumpt - Add `devcontainer.yaml` CI workflow that builds the container and validates tooling - Expand development guide with devcontainer quick-start instructions - Fix markdownlint warnings in bpftrace troubleshooting doc ## Related Issue Partially addresses #2027 (lint alignment will be handled in a follow-up PR) ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI will validate the devcontainer builds and all tools are available via the new `devcontainer.yaml` workflow. Signed-off-by: Quang Nguyen --- .devcontainer/devcontainer.json | 98 +++++++++++++++++++++++--- .devcontainer/installMoreTools.sh | 25 ------- .github/workflows/devcontainer.yaml | 46 ++++++++++++ docs/06-Troubleshooting/bpftrace.md | 3 + docs/08-Contributing/02-development.md | 17 ++++- 5 files changed, 152 insertions(+), 37 deletions(-) delete mode 100755 .devcontainer/installMoreTools.sh create mode 100644 .github/workflows/devcontainer.yaml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 25b94482ce..5a1882210a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,25 +2,101 @@ "name": "retina", "image": "mcr.microsoft.com/devcontainers/base:noble", "features": { - "ghcr.io/devcontainers/features/docker-in-docker:2": {}, - "ghcr.io/devcontainers/features/github-cli:1": {}, - "ghcr.io/devcontainers/features/go:1": { + "ghcr.io/devcontainers/features/docker-in-docker:2.16.1": {}, + "ghcr.io/devcontainers/features/github-cli:1.1.0": {}, + "ghcr.io/devcontainers/features/go:1.3.3": { "version": "1.24.11" }, - "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}, - "ghcr.io/devcontainers-extra/features/kind:1": {}, - "ghcr.io/devcontainers/features/azure-cli:1": {} + "ghcr.io/devcontainers/features/kubectl-helm-minikube:1.3.1": {}, + "ghcr.io/devcontainers-extra/features/kind:1.0.15": {}, + "ghcr.io/devcontainers/features/azure-cli:1.2.9": {}, + // LLVM 17 is the minimum version available for Ubuntu Noble on apt.llvm.org. + // Provides clang and llvm-strip needed for eBPF compilation. + "ghcr.io/devcontainers-community/features/llvm:3.2.0": { + "version": "17" + } + }, + "hostRequirements": { + "cpus": 4, + "memory": "8gb", + "storage": "32gb" + }, + // Persist Go module and build caches across container rebuilds. + "mounts": [ + { + "type": "volume", + "source": "retina-gomodcache", + "target": "/go/pkg/mod" + }, + { + "type": "volume", + "source": "retina-gobuildcache", + "target": "/home/vscode/.cache/go-build" + } + ], + // These commands run in parallel during container creation. + "onCreateCommand": { + // The LLVM feature installs versioned binaries (clang-17, llvm-strip-17). + // Create unversioned symlinks so the build system can find them. + "symlinks": "sudo ln -sf /usr/bin/clang-17 /usr/bin/clang && sudo ln -sf /usr/bin/llvm-strip-17 /usr/bin/llvm-strip", + // Fix ownership of volume mounts (created as root) and cache dirs, + // then download Go modules. + "go-setup": "sudo chown -R vscode:vscode /go /home/vscode/.cache && go mod download", + // Install jq (needed by some Makefile targets and scripts). + "apt-deps": "sudo apt-get update && sudo apt-get install -y --no-install-recommends jq && sudo rm -rf /var/lib/apt/lists/*" + }, + // Wait for Docker-in-Docker to be ready, then create a Kind cluster for local testing. + "postStartCommand": { + "kind": "while ! docker info >/dev/null 2>&1; do sleep 1; done && kind create cluster 2>/dev/null || true" + }, + "waitFor": "onCreateCommand", + "forwardPorts": [ + 9965, + 4244, + 10093 + ], + "portsAttributes": { + "9965": { + "label": "Hubble Metrics", + "onAutoForward": "silent" + }, + "4244": { + "label": "Hubble Relay", + "onAutoForward": "silent" + }, + "10093": { + "label": "Retina Metrics", + "onAutoForward": "silent" + } }, - "postCreateCommand": "bash .devcontainer/installMoreTools.sh && while ! docker info >/dev/null 2>&1; do sleep 1; done && kind create cluster", "customizations": { "vscode": { "extensions": [ - "esbenp.prettier-vscode", "golang.go", - "mutantdino.resourcemonitor", "ms-vscode.makefile-tools", - "ms-kubernetes-tools.vscode-kubernetes-tools" - ] + "ms-kubernetes-tools.vscode-kubernetes-tools", + "ms-azuretools.vscode-docker", + "redhat.vscode-yaml", + "mutantdino.resourcemonitor", + "DavidAnson.vscode-markdownlint" + ], + "settings": { + "go.lintTool": "golangci-lint", + "go.lintFlags": [ + "--config=.golangci.yaml", + "--timeout=10m" + ], + "go.formatTool": "gofumpt", + "files.insertFinalNewline": true, + "markdownlint.config": { + "extends": ".github/.markdownlint.json" + }, + "[markdown]": { + "editor.codeActionsOnSave": { + "source.fixAll.markdownlint": "explicit" + } + } + } } } } diff --git a/.devcontainer/installMoreTools.sh b/.devcontainer/installMoreTools.sh deleted file mode 100755 index 185ef14b93..0000000000 --- a/.devcontainer/installMoreTools.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -euo pipefail - -LLVM_VERSION=16 - -# Install the required tools and dependencies -sudo apt-get update && sudo apt-get install -y \ - lsb-release \ - wget \ - software-properties-common \ - gnupg \ - man-db - -# Install LLVM/Clang (version must match project requirements) -curl -fsSL https://apt.llvm.org/llvm.sh -o /tmp/llvm.sh -chmod +x /tmp/llvm.sh -sudo /tmp/llvm.sh "$LLVM_VERSION" -rm /tmp/llvm.sh - -# Create unversioned symlinks so the build system finds clang and llvm-strip -sudo ln -sf "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang -sudo ln -sf "/usr/bin/llvm-strip-${LLVM_VERSION}" /usr/bin/llvm-strip - -# Install gofumpt (used by make fmt) -go install mvdan.cc/gofumpt@latest diff --git a/.github/workflows/devcontainer.yaml b/.github/workflows/devcontainer.yaml new file mode 100644 index 0000000000..cdcba16086 --- /dev/null +++ b/.github/workflows/devcontainer.yaml @@ -0,0 +1,46 @@ +name: DevContainer +on: + merge_group: + push: + branches: [main] + paths: + - ".devcontainer/**" + - "go.mod" + pull_request: + branches: [main] + paths: + - ".devcontainer/**" + - "go.mod" + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build DevContainer + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Build and validate devcontainer + uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 # v0.3.1900000417 + with: + runCmd: | + clang --version + llvm-strip --version + go version + EXPECTED_GO=$(grep '^go ' go.mod | awk '{print $2}') + ACTUAL_GO=$(go version | grep -oP '\d+\.\d+\.\d+') + if [ "$EXPECTED_GO" != "$ACTUAL_GO" ]; then + echo "::error::Go version mismatch: devcontainer has $ACTUAL_GO but go.mod requires $EXPECTED_GO" + exit 1 + fi + kubectl version --client + helm version + kind version + grep -rl 'go:generate.*bpf2go' pkg/plugin/ | xargs -I{} go generate {} diff --git a/docs/06-Troubleshooting/bpftrace.md b/docs/06-Troubleshooting/bpftrace.md index 7c609613de..8e3ad0d180 100644 --- a/docs/06-Troubleshooting/bpftrace.md +++ b/docs/06-Troubleshooting/bpftrace.md @@ -5,6 +5,7 @@ The `retina bpftrace` command allows you to trace network issues on a Kubernetes node in real-time using eBPF/bpftrace. This is useful for debugging connectivity problems such as: + - Packet drops (with reason codes) - TCP RST events (connection resets) - Socket errors (ECONNREFUSED, ETIMEDOUT, etc.) @@ -60,6 +61,7 @@ The full list of drop reasons is kernel-version specific and is printed at the s ### RST_SENT / RST_RECV - TCP Reset Events Captures TCP RST packets sent or received. These indicate: + - Connection refused (no service listening) - Connection reset by peer - Firewall rejecting connections @@ -78,6 +80,7 @@ Captures socket-level errors reported to applications: ### RETRANS - TCP Retransmissions Captures TCP segment retransmissions, which indicate: + - Packet loss in the network - Network congestion - Slow or unresponsive peers diff --git a/docs/08-Contributing/02-development.md b/docs/08-Contributing/02-development.md index 6cfb562653..7f7ba22f29 100644 --- a/docs/08-Contributing/02-development.md +++ b/docs/08-Contributing/02-development.md @@ -6,7 +6,22 @@ This document provides steps to set up your dev environment and start contributi Retina uses a forking workflow. To contribute, fork the repository and create a branch for your changes. -The easiest way to set up your Development Environment is to use the provided GitHub Codespaces configuration. +### Using a devcontainer (recommended) + +The easiest way to get started is to use the provided [devcontainer](https://github.com/microsoft/retina/blob/main/.devcontainer/devcontainer.json), which works with both [GitHub Codespaces](https://github.com/features/codespaces) and [VS Code Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers). + +The devcontainer comes pre-configured with all required tools: + +- Go, clang/LLVM (for eBPF compilation), Docker, Helm, kubectl, Kind, Azure CLI, GitHub CLI, and jq +- Go modules are pre-downloaded; run `make generate` to compile eBPF programs and generate mocks before building +- A Kind cluster is created on startup for local testing +- VS Code is configured with golangci-lint and gofumpt so editor feedback matches CI + +To launch in Codespaces, click **Code > Codespaces > New codespace** on the repository page. To use locally, open the repository in VS Code and select **Reopen in Container** from the command palette. + +### Manual setup + +If you prefer to set up your environment manually, see the requirements below. ## Environment Config From 6fc7af17da4d6da0d4ff81078349debc97471816 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 13 Mar 2026 21:50:00 -0400 Subject: [PATCH 243/448] fix(ci): build kapinger arm64 natively instead of cross-compiling (#2096) # Description Currently the kapinger workflow cross-compiles all architectures (linux/amd64, linux/arm64, windows/amd64) from a single `--platform=linux/amd64` builder. The arm64 binary is built with `GOOS=linux GOARCH=arm64 go build`, which doesn't work reliably for CGO-dependent code and prevents using platform-specific optimizations. This PR restructures the workflow and Dockerfile for native builds: - **Dockerfile**: Split into a native Linux builder (runs on target arch) and a cross-compiling Windows builder (`--platform=$BUILDPLATFORM` with `GOOS=windows`). Fixed missing `/lib64/` copy that caused "no such file or directory" at runtime. - **Workflow**: Use a matrix strategy with native runners (`ubuntu-latest` for amd64, `ubuntu-24.04-arm` for arm64). Split into separate `build-linux`, `build-windows`, `manifest`, and `build-toolbox` jobs. - **Smoke test**: Each Linux build loads the image and verifies the binary starts correctly via `docker run`. - **Manifest**: After all builds pass, create a multi-arch manifest list (`docker buildx imagetools create`) combining linux-amd64, linux-arm64, and windows. - **Toolbox**: Add GHCR login and enable push on merge to main (previously build-only). - **CI hardening**: Add path filters, PR/merge_group triggers, `permissions`, GHCR login, and pin all action SHAs. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Additional Notes - Images are pushed only on merge to main, not on PRs. Signed-off-by: Quang Nguyen --- .github/workflows/kapinger.yaml | 150 ++++++++++++++++++++++++++------ hack/tools/kapinger/Dockerfile | 38 ++++---- 2 files changed, 139 insertions(+), 49 deletions(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 02069b0a61..e3100aee25 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -6,8 +6,18 @@ on: - main jobs: - build: - runs-on: ubuntu-latest + build-linux: + name: Build Linux Kapinger Image (${{ matrix.arch }}) + runs-on: ${{ matrix.runner }} + + strategy: + matrix: + arch: ["amd64", "arm64"] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout code @@ -16,50 +26,134 @@ jobs: - name: Set outputs id: vars run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - name: Check outputs - run: echo ${{ steps.vars.outputs.sha_short }} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + - name: Log in to GHCR + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - # - name: Login to GitHub Container Registry - # uses: docker/login-action@v1 - # with: - # registry: ghcr.io - # username: ${{ github.repository_owner }} - # password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - name: Build Windows Kapinger Image - uses: docker/build-push-action@v6 + - name: Build Linux Kapinger Image + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile - platforms: windows/amd64 + platforms: linux/${{ matrix.arch }} + target: linux + load: true push: false provenance: false - tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-windows + tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux-${{ matrix.arch }} - - name: Build Linux Kapinger Image - uses: docker/build-push-action@v6 + - name: Smoke test kapinger binary + run: | + IMAGE=ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux-${{ matrix.arch }} + # Verify the binary starts and prints the expected startup log. + # It will exit with an error because there's no K8s cluster, but + # that confirms the binary is correctly linked and executable. + docker run --rm "$IMAGE" 2>&1 | grep -q "starting kapinger" + + - name: Push Linux Kapinger Image + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile - platforms: linux/amd64 - push: false + platforms: linux/${{ matrix.arch }} + target: linux + push: true provenance: false - tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux + tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux-${{ matrix.arch }} + + build-windows: + name: Build Windows Kapinger Image + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set outputs + id: vars + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Log in to GHCR + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + + - name: Build Windows Kapinger Image + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: hack/tools/kapinger + file: hack/tools/kapinger/Dockerfile + platforms: windows/amd64 + target: windows + push: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) }} + provenance: false + tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-windows + + manifest: + name: Create and Push Manifest + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) + needs: [build-linux, build-windows] + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set outputs + id: vars + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Log in to GHCR + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + + - name: Create and push manifest + run: | + TAG=${{ steps.vars.outputs.sha_short }} + REPO=ghcr.io/${{ github.repository }}/kapinger + TAGS="-t $REPO:$TAG" + if [[ "${{ github.ref }}" == refs/tags/v* ]]; then + TAGS="$TAGS -t $REPO:${{ github.ref_name }}" + fi + docker buildx imagetools create $TAGS \ + "$REPO:$TAG-linux-amd64" \ + "$REPO:$TAG-linux-arm64" \ + "$REPO:$TAG-windows" + + build-toolbox: + name: Build Linux Toolbox Image + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set outputs + id: vars + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Log in to GHCR + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Linux Toolbox Image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: hack/tools file: hack/tools/toolbox/Dockerfile platforms: linux/amd64 - push: false + push: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) }} provenance: false tags: ghcr.io/${{ github.repository }}/toolbox:${{ steps.vars.outputs.sha_short }}-linux -# - name: Create and push manifest -# id: docker_manifest -# run: | -# docker manifest create ghcr.io/${{ github.repository }}/kapinger:latest ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-windows ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux -# docker manifest push ghcr.io/${{ github.repository }}/kapinger:latest diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 22be839b4b..640633867d 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,36 +1,32 @@ +# Linux builder - runs natively on the target platform (amd64 or arm64) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:66a04c4bcea1fafc935246c96af236eb4d91d501387e061ae59f134c8993dae9 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:9644874dae39c9ef28b59836911bc859c0a6c5c1c1d76429063f4b435275815b AS builder WORKDIR /build ADD . . -RUN go mod download +RUN go mod download +RUN go build -o kapinger . && mkdir -p /lib64 -# Build for Linux -RUN GOOS=linux go build -o kapinger . - -# Build for Windows -RUN GOOS=windows go build -o kapinger.exe . - -# Build for ARM64 Linux -RUN GOOS=linux GOARCH=arm64 go build -o kapinger-arm64 . - -FROM --platform=linux/amd64 scratch AS linux-amd64 +FROM scratch AS linux COPY --from=builder /lib/ /lib +COPY --from=builder /lib64/ /lib64 COPY --from=builder /usr/lib/ /usr/lib WORKDIR /app COPY --from=builder /build/kapinger . CMD ["./kapinger"] +# Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:66a04c4bcea1fafc935246c96af236eb4d91d501387e061ae59f134c8993dae9 AS windows-builder + +WORKDIR /build +ADD . . +RUN go mod download +RUN GOOS=windows go build -o kapinger.exe . + # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS windows-amd64 +FROM mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS windows WORKDIR /app -COPY --from=builder /build/kapinger.exe . +COPY --from=windows-builder /build/kapinger.exe . ENTRYPOINT [ "cmd.exe" ] CMD [ "/c", "kapinger.exe" ] - -FROM --platform=linux/arm64 scratch AS linux-arm64 -COPY --from=builder /lib/ /lib -COPY --from=builder /usr/lib/ /usr/lib -WORKDIR /app -COPY --from=builder /build/kapinger-arm64 . -CMD ["./kapinger-arm64"] From 60ed1c5dc2b1a5985ba16d476efbf66dd5432831 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 01:05:18 -0400 Subject: [PATCH 244/448] deps: bump actions/download-artifact from 8.0.0 to 8.0.1 (#2109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 8.0.0 to 8.0.1.
Release notes

Sourced from actions/download-artifact's releases.

v8.0.1

What's Changed

Full Changelog: https://github.com/actions/download-artifact/compare/v8...v8.0.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=8.0.0&new-version=8.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index cc9577ecf2..5a02e829df 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -133,7 +133,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index b40ddeef90..d7b3e600de 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -109,7 +109,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Windows Binaries - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: windows-binaries path: output/windows_amd64/ From 404f705ad56d86e0500936d410e4de154e334bf6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 13:32:30 -0400 Subject: [PATCH 245/448] deps: bump aquasecurity/trivy-action from 0.34.2 to 0.35.0 (#2103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.34.2 to 0.35.0.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.35.0

What's Changed

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/0.34.2...0.35.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.34.2&new-version=0.35.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 9b87f38c09..7cb7bc7a6f 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -39,7 +39,7 @@ jobs: echo "TAG=$TAG" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 # 0.34.2 + uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From c141b1d65164d0d6e47b2c4e1656f06d4c3f5523 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:32:46 +0000 Subject: [PATCH 246/448] deps: bump anchore/sbom-action from 0.23.0 to 0.23.1 (#2104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.23.0 to 0.23.1.
Release notes

Sourced from anchore/sbom-action's releases.

v0.23.1

⬆️ Dependencies

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anchore/sbom-action&package-manager=github_actions&previous-version=0.23.0&new-version=0.23.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 6ea2f7ca11..1265e0ab6d 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -29,7 +29,7 @@ jobs: with: go-version-file: go.mod - name: Install Syft - uses: anchore/sbom-action/download-syft@17ae1740179002c89186b61233e0f892c3118b11 # v0.23.0 + uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1 - name: Run GoReleaser build uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 env: @@ -53,7 +53,7 @@ jobs: with: go-version-file: go.mod - name: Install Syft - uses: anchore/sbom-action/download-syft@17ae1740179002c89186b61233e0f892c3118b11 # v0.23.0 + uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1 - name: Run GoReleaser release uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 with: From 56ea463a204520766b880a83907f91dc888c3b65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 19:21:29 +0000 Subject: [PATCH 247/448] deps: bump docker/build-push-action from 6 to 7 (#2101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.
Release notes

Sourced from docker/build-push-action's releases.

v7.0.0

Full Changelog: https://github.com/docker/build-push-action/compare/v6.19.2...v7.0.0

v6.19.2

Full Changelog: https://github.com/docker/build-push-action/compare/v6.19.1...v6.19.2

v6.19.1

Full Changelog: https://github.com/docker/build-push-action/compare/v6.19.0...v6.19.1

v6.19.0

Full Changelog: https://github.com/docker/build-push-action/compare/v6.18.0...v6.19.0

v6.18.0

[!NOTE] Build summary is now supported with Docker Build Cloud.

Full Changelog: https://github.com/docker/build-push-action/compare/v6.17.0...v6.18.0

v6.17.0

[!NOTE] Build record is now exported using the buildx history export command instead of the legacy export-build tool.

Full Changelog: https://github.com/docker/build-push-action/compare/v6.16.0...v6.17.0

v6.16.0

... (truncated)

Commits
  • d08e5c3 Merge pull request #1479 from docker/dependabot/npm_and_yarn/docker/actions-t...
  • cbd2dff chore: update generated content
  • f76f51f chore(deps): Bump @​docker/actions-toolkit from 0.78.0 to 0.79.0
  • 7d03e66 Merge pull request #1473 from crazy-max/rm-deprecated-envs
  • 98f853d chore: update generated content
  • cadccf6 remove deprecated envs
  • 03fe877 Merge pull request #1478 from docker/dependabot/github_actions/docker/setup-b...
  • 827e366 chore(deps): Bump docker/setup-buildx-action from 3 to 4
  • e25db87 Merge pull request #1474 from crazy-max/rm-export-build-tool
  • 1ac2573 Merge pull request #1470 from crazy-max/node24
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/build-push-action&package-manager=github_actions&previous-version=6&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/kapinger.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index e3100aee25..ec174a8ac9 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -35,7 +35,7 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Linux Kapinger Image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -56,7 +56,7 @@ jobs: - name: Push Linux Kapinger Image if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -86,7 +86,7 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Windows Kapinger Image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -149,7 +149,7 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Linux Toolbox Image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 with: context: hack/tools file: hack/tools/toolbox/Dockerfile From e227d586f86435c415c7c31ca25649a46cd82272 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 16:31:31 -0400 Subject: [PATCH 248/448] deps: bump sigstore/cosign-installer from 4.0.0 to 4.1.0 (#2105) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.0.0 to 4.1.0.
Release notes

Sourced from sigstore/cosign-installer's releases.

v4.1.0

What's Changed

We recommend updating as soon as possible as this includes bug fixes for Cosign. We also recommend removing with: cosign-release and strongly discourage using cosign-release unless you have a specific reason to use an older version of Cosign.

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v4.0.0...v4.1.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=4.0.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 218474b288..17a53112f4 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -28,7 +28,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index d7b3e600de..ea75a518ae 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -38,7 +38,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -115,7 +115,7 @@ jobs: path: output/windows_amd64/ - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -168,7 +168,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -216,7 +216,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -262,7 +262,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -308,7 +308,7 @@ jobs: uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From c0b6468e91635ec5988461e9e4dbb9706cb1dc28 Mon Sep 17 00:00:00 2001 From: Vipul Singh Date: Tue, 17 Mar 2026 06:44:53 -0700 Subject: [PATCH 249/448] fix: Use ValidationScheme for thee prom e2e (#2119) Use ValidationScheme as `model.LegacyValidation` so that the metrics labels are reuired to conform with the prom charater requirements. # Description Using ValidationScheme as `model.LegacyValidation` as the default validation scheme should not be used in practice. ``` // UnsetValidation represents an undefined ValidationScheme. // Should not be used in practice. UnsetValidation iota ``` https://pkg.go.dev/github.com/prometheus/common@v0.67.5/model#ValidationScheme This also needs a bump in prometheus/common module bump. Relevant dependabot PR: https://github.com/microsoft/retina/pull/1993 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Vipul Singh --- go.mod | 26 +++++----- go.sum | 52 +++++++++---------- .../retinaendpoint_controller_test.go | 7 ++- test/e2e/framework/prometheus/prometheus.go | 5 +- 4 files changed, 47 insertions(+), 43 deletions(-) diff --git a/go.mod b/go.mod index 330be0742f..2552fc6360 100644 --- a/go.mod +++ b/go.mod @@ -209,11 +209,11 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/mod v0.30.0 + golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/tools v0.39.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect @@ -238,14 +238,14 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/spf13/pflag v1.0.9 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.17.0 - golang.org/x/sys v0.38.0 - golang.org/x/term v0.34.0 // indirect - google.golang.org/protobuf v1.36.10 + golang.org/x/net v0.48.0 // indirect + golang.org/x/oauth2 v0.34.0 // indirect + golang.org/x/sync v0.19.0 + golang.org/x/sys v0.39.0 + golang.org/x/term v0.38.0 // indirect + google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 k8s.io/apimachinery v0.32.4 @@ -297,7 +297,7 @@ require ( github.com/onsi/gomega v1.38.2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 - github.com/prometheus/common v0.65.0 + github.com/prometheus/common v0.67.5 github.com/safchain/ethtool v0.7.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 @@ -640,7 +640,7 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect gocloud.dev v0.37.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect diff --git a/go.sum b/go.sum index 06e1b9f0bb..50dcee13ba 100644 --- a/go.sum +++ b/go.sum @@ -1254,8 +1254,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= -github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -1401,8 +1401,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +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/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= @@ -1593,8 +1593,8 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= @@ -1617,8 +1617,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1645,8 +1645,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1685,12 +1685,12 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1704,8 +1704,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1769,8 +1769,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1781,8 +1781,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1794,8 +1794,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1829,8 +1829,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -1882,8 +1882,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= diff --git a/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go b/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go index 60f02a7449..1f5a4444b5 100644 --- a/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go +++ b/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go @@ -227,8 +227,11 @@ func TestRetinaEndpointReconciler_ReconcilePod(t *testing.T) { require.Eventually(t, func() bool { err := client.Get(context.Background(), tt.fields.newlyCachedPod.Key, &got) fmt.Println(err) - return !apierrors.IsNotFound(err) - }, 5*time.Second, 1*time.Second, "RetinaEndpoint should be created") + if apierrors.IsNotFound(err) { + return false + } + return got.Spec.PodIP == tt.wantedRetinaEndpoint.Spec.PodIP + }, 5*time.Second, 1*time.Second, "RetinaEndpoint should be created/updated") require.Equal(t, *tt.wantedRetinaEndpoint, got) } }) diff --git a/test/e2e/framework/prometheus/prometheus.go b/test/e2e/framework/prometheus/prometheus.go index 811235547c..ebd0cb185c 100644 --- a/test/e2e/framework/prometheus/prometheus.go +++ b/test/e2e/framework/prometheus/prometheus.go @@ -13,6 +13,7 @@ import ( "github.com/microsoft/retina/test/retry" promclient "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" + "github.com/prometheus/common/model" ) var ( @@ -164,13 +165,13 @@ func verifyValidMetricPresentPartial(metricName string, data map[string]*promcli } func getAllPrometheusMetricsFromBuffer(buf []byte) (map[string]*promclient.MetricFamily, error) { - var parser expfmt.TextParser + parser := expfmt.NewTextParser(model.LegacyValidation) reader := strings.NewReader(string(buf)) return parser.TextToMetricFamilies(reader) //nolint } func ParseReaderPrometheusMetrics(input io.Reader) (map[string]*promclient.MetricFamily, error) { - var parser expfmt.TextParser + parser := expfmt.NewTextParser(model.LegacyValidation) return parser.TextToMetricFamilies(input) //nolint } From 48288a31f0c01e30525c4b49903b1a2b382f992c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:38:48 +0000 Subject: [PATCH 250/448] deps: bump opentofu/setup-opentofu from 1.0.8 to 2.0.0 (#2120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [opentofu/setup-opentofu](https://github.com/opentofu/setup-opentofu) from 1.0.8 to 2.0.0.
Release notes

Sourced from opentofu/setup-opentofu's releases.

v2.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/opentofu/setup-opentofu/compare/v1...v2.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=opentofu/setup-opentofu&package-manager=github_actions&previous-version=1.0.8&new-version=2.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test-multicloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 0dd6fac1fb..1268c5d87a 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 30 steps: - - uses: opentofu/setup-opentofu@9d84900f3238fab8cd84ce47d658d25dd008be2f # v1.0.8 + - uses: opentofu/setup-opentofu@fc711fa910b93cba0f3fbecaafc9f42fd0c411cb # v2.0.0 with: tofu_version: 1.8.3 From e384244da21160de7b1836db8ad57853823bf2f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:32:32 -0400 Subject: [PATCH 251/448] deps: bump azure/login from 2.3.0 to 3.0.0 (#2121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [azure/login](https://github.com/azure/login) from 2.3.0 to 3.0.0.
Release notes

Sourced from azure/login's releases.

Azure Login Action v3.0.0

What's Changed

Full Changelog: https://github.com/Azure/login/compare/v2.3.0...v3.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azure/login&package-manager=github_actions&previous-version=2.3.0&new-version=3.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e.yaml | 2 +- .github/workflows/images.yaml | 14 +++++++------- .github/workflows/perf-template.yaml | 2 +- .github/workflows/scale-test.yaml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index df038209df..6c23650830 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -96,7 +96,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 5a02e829df..b1134be36f 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -54,7 +54,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -139,7 +139,7 @@ jobs: path: output/windows_amd64/ - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -199,7 +199,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -252,7 +252,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -304,7 +304,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} @@ -357,7 +357,7 @@ jobs: uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Azure CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -389,7 +389,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} with: client-id: ${{ secrets.AZURE_CLIENT_ID }} diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index f9bf10aa32..f7ceae2b83 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -58,7 +58,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 with: client-id: ${{ secrets.azure-client-id }} tenant-id: ${{ secrets.azure-tenant-id }} diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 34c0891556..4c7acb6037 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -78,7 +78,7 @@ jobs: - run: go version - name: Az CLI login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 + uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} From bd314cbdc2dd3d1ebf84f5f71a49e3ebaae5b8eb Mon Sep 17 00:00:00 2001 From: Aanchal Khandelwal Date: Tue, 17 Mar 2026 14:44:22 -0400 Subject: [PATCH 252/448] feat: Make eBPF filter map max_entries configurable via config/env var (#2117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Feature: Configurable eBPF Filter Map Size The `retina_filter` eBPF map `max_entries` was hardcoded. This makes it configurable at runtime via Helm values or environment variable by overriding `MapSpec.MaxEntries` before loading the map into the kernel. **Configuration options:** - Helm values.yaml: `filterMapMaxEntries: 15000` - Environment variable: `RETINA_FILTERMAXMAPENTRIES=15000` - Default: 255 **Changes:** - Add `FilterMapMaxEntries` to Config struct with default of 255 - Modify `filter.Init()` to accept and apply `maxEntries` parameter - Thread config value through `bpf.Setup()`, `filtermanager.Init()`, and callers - Add Helm chart values and ConfigMap template support ## Related Issue Fixes #2085 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Testing Completed - Verified filter map initializes with configured `maxEntries` value via init container logs: ``` level=info caller=filter/filter_map_linux.go:63 msg="Filter map max entries configured" maxEntries=15000 ``` - Verified configurable via Helm values.yaml and ConfigMap - Verified default of 255 applies when not configured - Built and deployed multi-arch images (amd64 + arm64) successfully - `go build` passes for both `controller/main.go` and `init/retina/main_linux.go` ## Additional Notes - No breaking changes — default behavior is preserved - Windows stubs updated to match new function signatures --- --- cmd/standard/daemon.go | 2 +- .../helm/retina/templates/configmap.yaml | 1 + .../controller/helm/retina/values.yaml | 4 +++ init/retina/main_linux.go | 2 +- pkg/bpf/setup_linux.go | 4 +-- pkg/config/config.go | 11 +++++-- pkg/managers/filtermanager/manager_linux.go | 4 +-- pkg/managers/filtermanager/manager_windows.go | 2 +- pkg/managers/pluginmanager/pluginmanager.go | 2 +- pkg/managers/watchermanager/watchermanager.go | 4 +-- .../watchermanager/watchermanager_test.go | 7 ++-- pkg/plugin/dropreason/dropreason_linux.go | 5 +++ pkg/plugin/filter/filter_map_linux.go | 18 +++++++++-- pkg/plugin/filter/filter_map_windows.go | 2 +- pkg/plugin/packetparser/packetparser_linux.go | 6 ++++ pkg/watchers/apiserver/apiserver.go | 32 ++++++++++--------- pkg/watchers/apiserver/apiserver_test.go | 7 ++-- test/managers/filtermanager/main.go | 7 ++-- test/plugin/dropreason/main_linux.go | 2 +- test/plugin/packetparser/main_linux.go | 4 +-- test/watchers/apiserver/main.go | 7 ++-- test/watchers/veth/main.go | 3 +- 22 files changed, 89 insertions(+), 47 deletions(-) diff --git a/cmd/standard/daemon.go b/cmd/standard/daemon.go index 121bf70645..2c3194fe41 100644 --- a/cmd/standard/daemon.go +++ b/cmd/standard/daemon.go @@ -241,7 +241,7 @@ func (d *Daemon) Start() error { controllerCache := controllercache.New(pubSub) enrich := enricher.New(ctx, controllerCache) //nolint:govet // shadowing this err is fine - fm, err := filtermanager.Init(5) //nolint:gomnd // defaults + fm, err := filtermanager.Init(5, daemonConfig.FilterMapMaxEntries) //nolint:gomnd // defaults if err != nil { mainLogger.Fatal("unable to create filter manager", zap.Error(err)) } diff --git a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml index 7de5ce98a3..041aaa30ac 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml @@ -28,6 +28,7 @@ data: dataSamplingRate: {{ .Values.dataSamplingRate }} packetParserRingBuffer: {{ .Values.packetParserRingBuffer }} packetParserRingBufferSize: {{ .Values.packetParserRingBufferSize }} + filterMapMaxEntries: {{ .Values.filterMapMaxEntries }} {{- end}} --- {{- if .Values.os.windows}} diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index 8e2fbcb5e7..4323c23f64 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -68,6 +68,10 @@ packetParserRingBuffer: "disabled" # Invalid values cause startup to fail with a validation error. # This value is not applied when ring buffers are disabled. packetParserRingBufferSize: 8388608 +# Maximum number of entries in the eBPF filter map (retina_filter). +# This map tracks IP addresses of pods of interest for network observability. +# Default: 255. Increase for large clusters with many tracked pods. +filterMapMaxEntries: 255 imagePullSecrets: [] nameOverride: "retina" diff --git a/init/retina/main_linux.go b/init/retina/main_linux.go index f07ee1b919..7a2a3afb8a 100644 --- a/init/retina/main_linux.go +++ b/init/retina/main_linux.go @@ -58,7 +58,7 @@ func run(args ...string) error { } // Setup BPF - err = bpf.Setup(l) + err = bpf.Setup(l, cfg.FilterMapMaxEntries) if err != nil { return errors.Wrap(err, "failed to setup Retina bpf filesystem") } diff --git a/pkg/bpf/setup_linux.go b/pkg/bpf/setup_linux.go index a04cbdf172..10c8d61ee7 100644 --- a/pkg/bpf/setup_linux.go +++ b/pkg/bpf/setup_linux.go @@ -55,7 +55,7 @@ func mountBpfFs() error { return nil } -func Setup(l *zap.Logger) error { +func Setup(l *zap.Logger, filterMapMaxEntries uint32) error { err := mountBpfFs() if err != nil { return errors.Wrap(err, "failed to mount BPF filesystem") @@ -71,7 +71,7 @@ func Setup(l *zap.Logger) error { // Initialize the filter map. // This will create the filter map in kernel and pin it to /sys/fs/bpf. - _, err = filter.Init() + _, err = filter.Init(filterMapMaxEntries) if err != nil { return errors.Wrap(err, "failed to initialize filter map") } diff --git a/pkg/config/config.go b/pkg/config/config.go index 6c5fc5b307..5ab9174fd0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -45,8 +45,9 @@ var ( "telemetryInterval smaller than %v is not allowed", MinTelemetryInterval, ) - DefaultTelemetryInterval = 15 * time.Minute - DefaultSamplingRate uint32 = 1 + DefaultTelemetryInterval = 15 * time.Minute + DefaultSamplingRate uint32 = 1 + DefaultFilterMapMaxEntries uint32 = 255 ) func (l *Level) UnmarshalText(text []byte) error { @@ -121,6 +122,7 @@ type Config struct { DataSamplingRate uint32 `yaml:"dataSamplingRate"` PacketParserRingBuffer PacketParserRingBufferMode `yaml:"packetParserRingBuffer"` PacketParserRingBufferSize uint32 `yaml:"packetParserRingBufferSize"` + FilterMapMaxEntries uint32 `yaml:"filterMapMaxEntries"` } func GetConfig(cfgFilename string) (*Config, error) { @@ -175,6 +177,11 @@ func GetConfig(cfgFilename string) (*Config, error) { config.DataSamplingRate = DefaultSamplingRate } + // Default filter map max entries to 255 if not set. + if config.FilterMapMaxEntries == 0 { + config.FilterMapMaxEntries = DefaultFilterMapMaxEntries + } + switch config.PacketParserRingBuffer { //nolint:exhaustive // we only care about Auto and empty (default) here case "": config.PacketParserRingBuffer = PacketParserRingBufferDisabled diff --git a/pkg/managers/filtermanager/manager_linux.go b/pkg/managers/filtermanager/manager_linux.go index a275fc2fed..ff123d67c6 100644 --- a/pkg/managers/filtermanager/manager_linux.go +++ b/pkg/managers/filtermanager/manager_linux.go @@ -38,7 +38,7 @@ type FilterManager struct { // Total time: 7 seconds // The manager locks the cache during retry. // Suggest to keep retry to a small number (not more than 3). -func Init(retry int) (*FilterManager, error) { +func Init(retry int, filterMapMaxEntries uint32) (*FilterManager, error) { var err error if retry < 1 { return nil, errors.New("retry should be greater than 0") @@ -55,7 +55,7 @@ func Init(retry int) (*FilterManager, error) { if f.c == nil { f.c = getCache() } - f.fm, err = filter.Init() + f.fm, err = filter.Init(filterMapMaxEntries) return f, errors.Wrapf(err, "failed to initialize filter map") } diff --git a/pkg/managers/filtermanager/manager_windows.go b/pkg/managers/filtermanager/manager_windows.go index 4f285ca75f..c52621dcaf 100644 --- a/pkg/managers/filtermanager/manager_windows.go +++ b/pkg/managers/filtermanager/manager_windows.go @@ -11,7 +11,7 @@ import ( type FilterManager struct{} -func Init(_ int) (*FilterManager, error) { +func Init(_ int, _ uint32) (*FilterManager, error) { return nil, nil } diff --git a/pkg/managers/pluginmanager/pluginmanager.go b/pkg/managers/pluginmanager/pluginmanager.go index 2209f5cf1a..48db840837 100644 --- a/pkg/managers/pluginmanager/pluginmanager.go +++ b/pkg/managers/pluginmanager/pluginmanager.go @@ -53,7 +53,7 @@ func NewPluginManager(cfg *kcfg.Config, tel telemetry.Telemetry) (*PluginManager if mgr.cfg.EnablePodLevel { mgr.l.Info("plugin manager has pod level enabled") - mgr.watcherManager = watchermanager.NewWatcherManager() + mgr.watcherManager = watchermanager.NewWatcherManager(mgr.cfg.FilterMapMaxEntries) } else { mgr.l.Info("plugin manager has pod level disabled") } diff --git a/pkg/managers/watchermanager/watchermanager.go b/pkg/managers/watchermanager/watchermanager.go index 55617db286..be945e0796 100644 --- a/pkg/managers/watchermanager/watchermanager.go +++ b/pkg/managers/watchermanager/watchermanager.go @@ -19,11 +19,11 @@ const ( DefaultRefreshRate = 30 * time.Second ) -func NewWatcherManager() *WatcherManager { +func NewWatcherManager(filterMapMaxEntries uint32) *WatcherManager { return &WatcherManager{ Watchers: []IWatcher{ endpoint.Watcher(), - apiserver.Watcher(), + apiserver.Watcher(filterMapMaxEntries), }, l: log.Logger().Named("watcher-manager"), refreshRate: DefaultRefreshRate, diff --git a/pkg/managers/watchermanager/watchermanager_test.go b/pkg/managers/watchermanager/watchermanager_test.go index 37dcf4809f..bdc8d3af04 100644 --- a/pkg/managers/watchermanager/watchermanager_test.go +++ b/pkg/managers/watchermanager/watchermanager_test.go @@ -7,6 +7,7 @@ import ( "errors" "testing" + kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" mock "github.com/microsoft/retina/pkg/managers/watchermanager/mocks" "github.com/stretchr/testify/require" @@ -20,7 +21,7 @@ func TestStopWatcherManagerGracefully(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() log.SetupZapLogger(log.GetDefaultLogOpts()) - mgr := NewWatcherManager() + mgr := NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) mockAPIServerWatcher := mock.NewMockIWatcher(ctl) mockEndpointWatcher := mock.NewMockIWatcher(ctl) @@ -56,7 +57,7 @@ func TestWatcherInitFailsGracefully(t *testing.T) { mockAPIServerWatcher := mock.NewMockIWatcher(ctl) mockEndpointWatcher := mock.NewMockIWatcher(ctl) - mgr := NewWatcherManager() + mgr := NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) mgr.Watchers = []IWatcher{ mockAPIServerWatcher, mockEndpointWatcher, @@ -74,7 +75,7 @@ func TestWatcherStopWithoutStart(t *testing.T) { defer ctl.Finish() log.SetupZapLogger(log.GetDefaultLogOpts()) - mgr := NewWatcherManager() + mgr := NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) err := mgr.Stop(context.Background()) require.Nil(t, err, "Expected no error when stopping watcher manager without starting it") diff --git a/pkg/plugin/dropreason/dropreason_linux.go b/pkg/plugin/dropreason/dropreason_linux.go index d660ddaf6d..d0b784a78e 100644 --- a/pkg/plugin/dropreason/dropreason_linux.go +++ b/pkg/plugin/dropreason/dropreason_linux.go @@ -144,6 +144,11 @@ func (dr *dropReason) Init() error { return err } + // Override filter map max entries to match the configured size from init container. + if mapSpec, ok := spec.Maps[plugincommon.FilterMapName]; ok && dr.cfg.FilterMapMaxEntries > 0 { + mapSpec.MaxEntries = dr.cfg.FilterMapMaxEntries + } + // TODO remove the opts if err := spec.LoadAndAssign(objs, &ebpf.CollectionOptions{ Programs: ebpf.ProgramOptions{ diff --git a/pkg/plugin/filter/filter_map_linux.go b/pkg/plugin/filter/filter_map_linux.go index 061ae7313d..e2b626f8ae 100644 --- a/pkg/plugin/filter/filter_map_linux.go +++ b/pkg/plugin/filter/filter_map_linux.go @@ -34,7 +34,7 @@ type FilterMap struct { batchApiNotSupported bool } -func Init() (*FilterMap, error) { +func Init(maxEntries uint32) (*FilterMap, error) { once.Do(func() { f = &FilterMap{} }) @@ -51,8 +51,20 @@ func Init() (*FilterMap, error) { return f, err } - obj := &filterObjects{} //nolint:typecheck - err := loadFilterObjects(obj, &ebpf.CollectionOptions{ //nolint:typecheck + spec, err := loadFilter() //nolint:typecheck // generated by bpf2go + if err != nil { + f.l.Error("loadFilter failed", zap.Error(err)) + return f, err + } + + // Override the filter map max entries from config. + if mapSpec, ok := spec.Maps["retina_filter"]; ok && maxEntries > 0 { + mapSpec.MaxEntries = maxEntries + f.l.Info("Filter map max entries configured", zap.Uint32("maxEntries", maxEntries)) + } + + obj := &filterObjects{} //nolint:typecheck // generated by bpf2go + err = spec.LoadAndAssign(obj, &ebpf.CollectionOptions{ Maps: ebpf.MapOptions{ PinPath: plugincommon.MapPath, }, diff --git a/pkg/plugin/filter/filter_map_windows.go b/pkg/plugin/filter/filter_map_windows.go index d7968bacca..c176994afa 100644 --- a/pkg/plugin/filter/filter_map_windows.go +++ b/pkg/plugin/filter/filter_map_windows.go @@ -7,7 +7,7 @@ import "net" type FilterMap struct{} -func Init() (*FilterMap, error) { +func Init(_ uint32) (*FilterMap, error) { return &FilterMap{}, nil } diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index 85c53b2241..9e443eec8a 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -245,6 +245,12 @@ func (p *packetParser) Init() error { if err != nil { return err } + + // Override filter map max entries to match the configured size from init container. + if mapSpec, ok := spec.Maps[plugincommon.FilterMapName]; ok && p.cfg.FilterMapMaxEntries > 0 { + mapSpec.MaxEntries = p.cfg.FilterMapMaxEntries + } + //nolint:typecheck if err := spec.LoadAndAssign(objs, &ebpf.CollectionOptions{ //nolint:typecheck Maps: ebpf.MapOptions{ diff --git a/pkg/watchers/apiserver/apiserver.go b/pkg/watchers/apiserver/apiserver.go index f047276bef..defcbcf55e 100644 --- a/pkg/watchers/apiserver/apiserver.go +++ b/pkg/watchers/apiserver/apiserver.go @@ -30,27 +30,29 @@ const ( ) type ApiServerWatcher struct { - isRunning bool - l *log.ZapLogger - current cache - new cache - apiServerHostName string - hostResolver IHostResolver - filterManager fm.IFilterManager - restConfig *rest.Config - client kclient.Client + isRunning bool + l *log.ZapLogger + current cache + new cache + apiServerHostName string + hostResolver IHostResolver + filterManager fm.IFilterManager + restConfig *rest.Config + client kclient.Client + filterMapMaxEntries uint32 } var a *ApiServerWatcher // Watcher creates a new ApiServerWatcher instance. -func Watcher() *ApiServerWatcher { +func Watcher(filterMapMaxEntries uint32) *ApiServerWatcher { if a == nil { a = &ApiServerWatcher{ - isRunning: false, - l: log.Logger().Named("apiserver-watcher"), - current: make(cache), - hostResolver: net.DefaultResolver, + isRunning: false, + l: log.Logger().Named("apiserver-watcher"), + current: make(cache), + hostResolver: net.DefaultResolver, + filterMapMaxEntries: filterMapMaxEntries, } } @@ -66,7 +68,7 @@ func (a *ApiServerWatcher) Init(ctx context.Context) error { // Get filter manager. if a.filterManager == nil { var err error - a.filterManager, err = fm.Init(filterManagerRetries) + a.filterManager, err = fm.Init(filterManagerRetries, a.filterMapMaxEntries) if err != nil { a.l.Error("failed to init filter manager", zap.Error(err)) return fmt.Errorf("failed to init filter manager: %w", err) diff --git a/pkg/watchers/apiserver/apiserver_test.go b/pkg/watchers/apiserver/apiserver_test.go index 24d7748d71..58659487dc 100644 --- a/pkg/watchers/apiserver/apiserver_test.go +++ b/pkg/watchers/apiserver/apiserver_test.go @@ -12,6 +12,7 @@ import ( "testing" "time" + kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" filtermanagermocks "github.com/microsoft/retina/pkg/managers/filtermanager" "github.com/microsoft/retina/pkg/watchers/apiserver/mocks" @@ -31,11 +32,11 @@ var errDNS = errors.New("DNS error") func TestGetWatcher(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) - a := Watcher() + a := Watcher(kcfg.DefaultFilterMapMaxEntries) assert.NotNil(t, a) - a_again := Watcher() - assert.Equal(t, a, a_again, "Expected the same veth watcher instance") + aAgain := Watcher(kcfg.DefaultFilterMapMaxEntries) + assert.Equal(t, a, aAgain, "Expected the same veth watcher instance") } func TestAPIServerWatcherStop(t *testing.T) { diff --git a/test/managers/filtermanager/main.go b/test/managers/filtermanager/main.go index 7de2a9fd89..e2cf604dda 100644 --- a/test/managers/filtermanager/main.go +++ b/test/managers/filtermanager/main.go @@ -13,6 +13,7 @@ import ( "strings" "time" + kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/managers/filtermanager" "github.com/microsoft/retina/pkg/managers/watchermanager" @@ -37,8 +38,8 @@ func main() { ctx := context.Background() // watcher manager - wm := watchermanager.NewWatcherManager() - wm.Watchers = []watchermanager.IWatcher{endpoint.Watcher(), apiserver.Watcher()} + wm := watchermanager.NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) + wm.Watchers = []watchermanager.IWatcher{endpoint.Watcher(), apiserver.Watcher(kcfg.DefaultFilterMapMaxEntries)} err := wm.Start(ctx) if err != nil { @@ -52,7 +53,7 @@ func main() { }() // Filtermanager. - f, err := filtermanager.Init(5) + f, err := filtermanager.Init(5, kcfg.DefaultFilterMapMaxEntries) if err != nil { l.Error("Failed to start Filtermanager", zap.Error(err)) panic(err) diff --git a/test/plugin/dropreason/main_linux.go b/test/plugin/dropreason/main_linux.go index e38fa4c9a3..189ffbaec7 100644 --- a/test/plugin/dropreason/main_linux.go +++ b/test/plugin/dropreason/main_linux.go @@ -34,7 +34,7 @@ func main() { } // Filtermanager. - f, err := filtermanager.Init(3) + f, err := filtermanager.Init(3, kcfg.DefaultFilterMapMaxEntries) if err != nil { l.Error("Start filtermanager failed", zap.Error(err)) return diff --git a/test/plugin/packetparser/main_linux.go b/test/plugin/packetparser/main_linux.go index 2596dd1fe7..4686437281 100644 --- a/test/plugin/packetparser/main_linux.go +++ b/test/plugin/packetparser/main_linux.go @@ -32,7 +32,7 @@ func main() { ctxTimeout, cancel := context.WithTimeout(context.Background(), 30*time.Second) // watcher manager - wm := watchermanager.NewWatcherManager() + wm := watchermanager.NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) wm.Watchers = []watchermanager.IWatcher{endpoint.Watcher()} err := wm.Start(ctxTimeout) @@ -46,7 +46,7 @@ func main() { } }() // Filtermanager. - f, err := filtermanager.Init(3) + f, err := filtermanager.Init(3, kcfg.DefaultFilterMapMaxEntries) if err != nil { l.Error("Start filtermanager failed", zap.Error(err)) return diff --git a/test/watchers/apiserver/main.go b/test/watchers/apiserver/main.go index 4703e12922..60905500b8 100644 --- a/test/watchers/apiserver/main.go +++ b/test/watchers/apiserver/main.go @@ -8,6 +8,7 @@ import ( "context" "time" + kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/managers/filtermanager" "github.com/microsoft/retina/pkg/managers/watchermanager" @@ -24,7 +25,7 @@ func main() { ctx := context.Background() // Filtermanager. - f, err := filtermanager.Init(5) + f, err := filtermanager.Init(5, kcfg.DefaultFilterMapMaxEntries) if err != nil { l.Error("Failed to start Filtermanager", zap.Error(err)) panic(err) @@ -35,8 +36,8 @@ func main() { } }() // watcher manager - wm := watchermanager.NewWatcherManager() - wm.Watchers = []watchermanager.IWatcher{apiserver.Watcher()} + wm := watchermanager.NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) + wm.Watchers = []watchermanager.IWatcher{apiserver.Watcher(kcfg.DefaultFilterMapMaxEntries)} // apiserver watcher. err = wm.Start(ctx) diff --git a/test/watchers/veth/main.go b/test/watchers/veth/main.go index 50a00c1c01..46343de747 100644 --- a/test/watchers/veth/main.go +++ b/test/watchers/veth/main.go @@ -8,6 +8,7 @@ import ( "context" "time" + kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/managers/watchermanager" "github.com/microsoft/retina/pkg/watchers/endpoint" @@ -23,7 +24,7 @@ func main() { ctx := context.Background() // watcher manager - wm := watchermanager.NewWatcherManager() + wm := watchermanager.NewWatcherManager(kcfg.DefaultFilterMapMaxEntries) wm.Watchers = []watchermanager.IWatcher{endpoint.Watcher()} err := wm.Start(ctx) From e51a61ff4b044646219bef7c26e57238603043d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:27:34 +0000 Subject: [PATCH 253/448] deps: bump github/codeql-action from 4.32.6 to 4.33.0 (#2115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.6 to 4.33.0.
Release notes

Sourced from github/codeql-action's releases.

v4.33.0

  • Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. #3562

    To opt out of this change:

    • Repositories owned by an organization: Create a custom repository property with the name github-codeql-file-coverage-on-prs and the type "True/false", then set this property to true in the repository's settings. For more information, see Managing custom properties for repositories in your organization. Alternatively, if you are using an advanced setup workflow, you can set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using default setup: Switch to an advanced setup workflow and set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using advanced setup: Set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
  • Fixed a bug which caused the CodeQL Action to fail loading repository properties if a "Multi select" repository property was configured for the repository. #3557

  • The CodeQL Action now loads custom repository properties on GitHub Enterprise Server, enabling the customization of features such as github-codeql-disable-overlay that was previously only available on GitHub.com. #3559

  • Once private package registries can be configured with OIDC-based authentication for organizations, the CodeQL Action will now be able to accept such configurations. #3563

  • Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". #3564

  • A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. #3570

Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.33.0 - 16 Mar 2026

  • Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. #3562

    To opt out of this change:

    • Repositories owned by an organization: Create a custom repository property with the name github-codeql-file-coverage-on-prs and the type "True/false", then set this property to true in the repository's settings. For more information, see Managing custom properties for repositories in your organization. Alternatively, if you are using an advanced setup workflow, you can set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using default setup: Switch to an advanced setup workflow and set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using advanced setup: Set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
  • Fixed a bug which caused the CodeQL Action to fail loading repository properties if a "Multi select" repository property was configured for the repository. #3557

  • The CodeQL Action now loads custom repository properties on GitHub Enterprise Server, enabling the customization of features such as github-codeql-disable-overlay that was previously only available on GitHub.com. #3559

  • Once private package registries can be configured with OIDC-based authentication for organizations, the CodeQL Action will now be able to accept such configurations. #3563

  • Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". #3564

  • A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. #3570

4.32.6 - 05 Mar 2026

  • Update default CodeQL bundle version to 2.24.3. #3548

4.32.5 - 02 Mar 2026

  • Repositories owned by an organization can now set up the github-codeql-disable-overlay custom repository property to disable improved incremental analysis for CodeQL. First, create a custom repository property with the name github-codeql-disable-overlay and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to true to disable improved incremental analysis. For more information, see Managing custom properties for repositories in your organization. This feature is not yet available on GitHub Enterprise Server. #3507
  • Added an experimental change so that when improved incremental analysis fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. #3487
  • The minimum memory check for improved incremental analysis is now skipped for CodeQL 2.24.3 and later, which has reduced peak RAM usage. #3515
  • Reduced log levels for best-effort private package registry connection check failures to reduce noise from workflow annotations. #3516
  • Added an experimental change which lowers the minimum disk space requirement for improved incremental analysis, enabling it to run on standard GitHub Actions runners. We expect to roll this change out to everyone in March. #3498
  • Added an experimental change which allows the start-proxy action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. #3512
  • The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. #3503, #3504

4.32.4 - 20 Feb 2026

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473
  • When the CodeQL Action is run with debugging enabled in Default Setup and private package registries are configured, the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. #3486
  • Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. #3485
  • Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a nightly CodeQL CLI release instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. #3484

4.32.3 - 13 Feb 2026

  • Added experimental support for testing connections to private package registries. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. #3466

4.32.2 - 05 Feb 2026

... (truncated)

Commits
  • b1bff81 Merge pull request #3574 from github/update-v4.32.7-7dd76e6bf
  • e682234 Add changelog entry for #3570
  • 95be291 Bump minor version
  • 59bcb60 Update changelog for v4.32.7
  • 7dd76e6 Merge pull request #3572 from github/mbg/pr-checks/eslint
  • e3200e3 Merge pull request #3563 from github/mbg/private-registry/oidc
  • 4c356c7 Merge pull request #3570 from github/mbg/repo-props/warn-on-unexpected-props
  • b4937c1 Only emit one message with accumulated property names
  • 136b8ab Remove cache-dependency-path options as well
  • a5aba59 Remove package-lock.json that's no longer needed
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.32.6&new-version=4.33.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mathew Merrick --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 109b502f2a..e07cc9b365 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/autobuild@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 7cb7bc7a6f..d5f88b0183 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/upload-sarif@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 with: sarif_file: "trivy-results.sarif" From 5e7be1fde741ff587795273712261c5c32d1f258 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 18 Mar 2026 21:55:18 -0400 Subject: [PATCH 254/448] fix(ci): add packages:write permission to kapinger workflow (#2113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The kapinger and toolbox image builds fail on push to `main` with `denied: installation not allowed to Create organization package` because the workflow lacks explicit `packages: write` permission. The `release-images.yaml` workflow (which successfully pushes agent/operator images) has this permission — `kapinger.yaml` was simply missing it. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI-only change. The fix aligns `kapinger.yaml` permissions with `release-images.yaml` which pushes successfully. ## Additional Notes Failing run: https://github.com/microsoft/retina/actions/runs/23078479890 Signed-off-by: Quang Nguyen --- .github/workflows/kapinger.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index ec174a8ac9..e6482e893d 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -5,6 +5,10 @@ on: branches: - main +permissions: + contents: read + packages: write + jobs: build-linux: name: Build Linux Kapinger Image (${{ matrix.arch }}) From c6e26519251daaad033811e1851caf5ca31f2e61 Mon Sep 17 00:00:00 2001 From: Brian Ugie Date: Thu, 19 Mar 2026 18:02:42 -0700 Subject: [PATCH 255/448] feat: Add TCX support to the packetparser plugin (#1994) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description

Add TCX support to packetparser plugin

Adds support for attaching BPF programs via TCX (TC eXpress), the newer kernel hook available in Linux 6.6+, as an alternative to the traditional clsact qdisc approach. TCX provides lower overhead and better multi-program chaining semantics.

Approach

Rather than a separate plugin, TCX attachment lives inside the existing packetparser plugin. The existing C programs (SEC("classifier_...")) require no changes — they are BPF_PROG_TYPE_SCHED_CLS programs and can be attached via either mechanism.

Configuration

A new enableTCX config field gates the feature:

Value | Behaviour -- | -- off | Always use traditional TC (default-safe) auto | Probe kernel support; use TCX if available, fall back to TC

Defaults to auto when unset.

Implementation details

  • Kernel probeisTCXSupported() creates a minimal throwaway SchedCLS program and attempts a TCX attach to loopback to detect kernel support without relying on the plugin's own loaded programs.
  • Unified attachment maptcMap/tcValue replaced with attachmentMap/attachmentValue, which tracks whether each interface was attached via TC or TCX and cleans up correctly on removal.
  • createQdiscAndAttach delegates to attachViaTCX or attachViaTC depending on p.tcxSupported, set once during Init().
## Related Issue https://github.com/microsoft/retina/issues/1958 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Brian Ugie Signed-off-by: Brian Ugie --- .../controller/helm/retina/values.yaml | 5 + .../helm/retina/templates/configmap.yaml | 1 + pkg/config/config.go | 22 +++ pkg/config/config_test.go | 42 +++++ pkg/config/testwith/config-tcx-auto.yaml | 6 + pkg/config/testwith/config-tcx-empty.yaml | 5 + pkg/config/testwith/config-tcx-invalid.yaml | 6 + pkg/config/testwith/config-tcx-off.yaml | 6 + pkg/managers/pluginmanager/pluginmanager.go | 12 +- pkg/plugin/packetparser/packetparser_linux.go | 178 ++++++++++++++++-- .../packetparser/packetparser_linux_test.go | 29 ++- pkg/plugin/packetparser/types_linux.go | 33 +++- 12 files changed, 299 insertions(+), 46 deletions(-) create mode 100644 pkg/config/testwith/config-tcx-auto.yaml create mode 100644 pkg/config/testwith/config-tcx-empty.yaml create mode 100644 pkg/config/testwith/config-tcx-invalid.yaml create mode 100644 pkg/config/testwith/config-tcx-off.yaml diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 2e8b582ec8..0dd54b5200 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -101,6 +101,11 @@ logLevel: info enabledPlugin_linux: '["linuxutil","packetforward","packetparser","dns", "dropreason"]' enabledPlugin_win: '["hnsstats"]' +# TCX Support +# Supported Values: "auto", "off" +# Default: auto +enableTCX: "auto" + enableTelemetry: false # Interval, in duration, to scrape/publish metrics. diff --git a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml index 041aaa30ac..61974ff10a 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml @@ -17,6 +17,7 @@ data: enabledPlugin: {{ .Values.enabledPlugin_linux }} metricsInterval: {{ .Values.metricsInterval }} metricsIntervalDuration: {{ .Values.metricsIntervalDuration }} + enableTCX: {{ .Values.enableTCX }} enableTelemetry: {{ .Values.enableTelemetry }} enablePodLevel: {{ .Values.enablePodLevel }} enableConntrackMetrics: {{ .Values.enableConntrackMetrics }} diff --git a/pkg/config/config.go b/pkg/config/config.go index 5ab9174fd0..6f26f50cc3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -17,6 +17,16 @@ import ( // Level defines the level of monitor aggregation. type Level int +// TCXMode controls whether TCX (TC eXpress) attachment is used for packetparser. +type TCXMode string + +const ( + // TCXModeAuto detects kernel support and uses TCX if available, falling back to TC. + TCXModeAuto TCXMode = "auto" + // TCXModeOff disables TCX and always uses traditional TC. + TCXModeOff TCXMode = "off" +) + const MinTelemetryInterval time.Duration = 2 * time.Minute const ( @@ -33,6 +43,7 @@ const ( ) var ( + ErrEnableTCXInvalid = errors.New("enableTCX must be \"auto\" or \"off\"") ErrPacketParserRingBufferAutoNotSupported = errors.New("packetParserRingBuffer mode auto is not supported yet") ErrPacketParserRingBufferInvalid = errors.New("packetParserRingBuffer must be set to enabled or disabled") ErrPacketParserRingBufferInvalidBool = errors.New( @@ -123,6 +134,7 @@ type Config struct { PacketParserRingBuffer PacketParserRingBufferMode `yaml:"packetParserRingBuffer"` PacketParserRingBufferSize uint32 `yaml:"packetParserRingBufferSize"` FilterMapMaxEntries uint32 `yaml:"filterMapMaxEntries"` + EnableTCX TCXMode `yaml:"enableTCX"` } func GetConfig(cfgFilename string) (*Config, error) { @@ -182,6 +194,16 @@ func GetConfig(cfgFilename string) (*Config, error) { config.FilterMapMaxEntries = DefaultFilterMapMaxEntries } + // Default EnableTCX to "auto" if unset, reject unknown values. + switch config.EnableTCX { + case "": + config.EnableTCX = TCXModeAuto + case TCXModeAuto, TCXModeOff: + // valid + default: + return nil, fmt.Errorf("invalid enableTCX %q: %w", config.EnableTCX, ErrEnableTCXInvalid) + } + switch config.PacketParserRingBuffer { //nolint:exhaustive // we only care about Auto and empty (default) here case "": config.PacketParserRingBuffer = PacketParserRingBufferDisabled diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 7b899e3524..3d4df8432c 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -70,6 +70,48 @@ func TestDecodeLevelHook(t *testing.T) { } } +func TestGetConfig_EnableTCX(t *testing.T) { + tests := []struct { + name string + configFile string + expected TCXMode + expectedError error + }{ + { + name: "auto", + configFile: "./testwith/config-tcx-auto.yaml", + expected: TCXModeAuto, + }, + { + name: "off", + configFile: "./testwith/config-tcx-off.yaml", + expected: TCXModeOff, + }, + { + name: "empty defaults to auto", + configFile: "./testwith/config-tcx-empty.yaml", + expected: TCXModeAuto, + }, + { + name: "invalid value rejected", + configFile: "./testwith/config-tcx-invalid.yaml", + expectedError: ErrEnableTCXInvalid, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg, err := GetConfig(tt.configFile) + if tt.expectedError != nil { + require.ErrorIs(t, err, tt.expectedError) + return + } + require.NoError(t, err) + assert.Equal(t, tt.expected, cfg.EnableTCX) + }) + } +} + func TestDecodePacketParserRingBufferModeHook(t *testing.T) { tests := []struct { name string diff --git a/pkg/config/testwith/config-tcx-auto.yaml b/pkg/config/testwith/config-tcx-auto.yaml new file mode 100644 index 0000000000..f3b75199c5 --- /dev/null +++ b/pkg/config/testwith/config-tcx-auto.yaml @@ -0,0 +1,6 @@ +apiServer: + host: "0.0.0.0" + port: 10093 +metricsIntervalDuration: "10s" +telemetryInterval: "15m" +enableTCX: "auto" diff --git a/pkg/config/testwith/config-tcx-empty.yaml b/pkg/config/testwith/config-tcx-empty.yaml new file mode 100644 index 0000000000..1a299f95fe --- /dev/null +++ b/pkg/config/testwith/config-tcx-empty.yaml @@ -0,0 +1,5 @@ +apiServer: + host: "0.0.0.0" + port: 10093 +metricsIntervalDuration: "10s" +telemetryInterval: "15m" diff --git a/pkg/config/testwith/config-tcx-invalid.yaml b/pkg/config/testwith/config-tcx-invalid.yaml new file mode 100644 index 0000000000..ab48e26fd3 --- /dev/null +++ b/pkg/config/testwith/config-tcx-invalid.yaml @@ -0,0 +1,6 @@ +apiServer: + host: "0.0.0.0" + port: 10093 +metricsIntervalDuration: "10s" +telemetryInterval: "15m" +enableTCX: "always" diff --git a/pkg/config/testwith/config-tcx-off.yaml b/pkg/config/testwith/config-tcx-off.yaml new file mode 100644 index 0000000000..7ccf75cce8 --- /dev/null +++ b/pkg/config/testwith/config-tcx-off.yaml @@ -0,0 +1,6 @@ +apiServer: + host: "0.0.0.0" + port: 10093 +metricsIntervalDuration: "10s" +telemetryInterval: "15m" +enableTCX: "off" diff --git a/pkg/managers/pluginmanager/pluginmanager.go b/pkg/managers/pluginmanager/pluginmanager.go index 48db840837..cbb5619e59 100644 --- a/pkg/managers/pluginmanager/pluginmanager.go +++ b/pkg/managers/pluginmanager/pluginmanager.go @@ -26,11 +26,15 @@ const ( // In any run I haven't seen reconcile take longer than 5 seconds, // and 10 seconds seems like a reasonable SLA for reconciliation to be completed MAX_RECONCILE_TIME = 10 * time.Second + + // plugin name used for conntrack GC check + pluginNamePacketparser = "packetparser" ) var ( - ErrNilCfg = errors.New("pluginmanager requires a non-nil config") - ErrZeroInterval = errors.New("pluginmanager requires a positive MetricsInterval in its config") + ErrNilCfg = errors.New("pluginmanager requires a non-nil config") + ErrZeroInterval = errors.New("pluginmanager requires a positive MetricsInterval in its config") + ErrPluginNotFound = errors.New("plugin not found in registry") ) type PluginManager struct { @@ -61,7 +65,7 @@ func NewPluginManager(cfg *kcfg.Config, tel telemetry.Telemetry) (*PluginManager for _, name := range cfg.EnabledPlugin { newPluginFn, ok := plugin.Get(name) if !ok { - return nil, fmt.Errorf("plugin %s not found in registry", name) + return nil, errors.Wrapf(ErrPluginNotFound, "%s", name) } mgr.plugins[name] = newPluginFn(mgr.cfg) } @@ -136,7 +140,7 @@ func (p *PluginManager) Start(ctx context.Context) error { } g, ctx := errgroup.WithContext(ctx) - _, isPacketParserEnabled := p.plugins["packetparser"] + _, isPacketParserEnabled := p.plugins[pluginNamePacketparser] // run conntrack GC only if packetparser is enabled if isPacketParserEnabled { ct, connErr := conntrack.New() diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index 9e443eec8a..f4bf4a2beb 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -20,6 +20,8 @@ import ( "github.com/cilium/cilium/api/v1/flow" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/asm" + "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/perf" "github.com/cilium/ebpf/ringbuf" tc "github.com/florianl/go-tc" @@ -306,9 +308,25 @@ func (p *packetParser) Init() error { p.reader = &perfReaderWrapper{reader: pr} } - p.tcMap = &sync.Map{} + p.attachmentMap = &sync.Map{} p.interfaceLockMap = &sync.Map{} + // Resolve TCX support based on config. + switch p.cfg.EnableTCX { + case kcfg.TCXModeOff: + p.tcxSupported = false + p.l.Info("EnableTCX=off: will use traditional TC attachment") + case kcfg.TCXModeAuto: + p.tcxSupported = isTCXSupported() + if p.tcxSupported { + p.l.Info("EnableTCX=auto: TCX supported, will use TCX attachment") + } else { + p.l.Info("EnableTCX=auto: TCX not supported, will use traditional TC attachment") + } + default: + p.l.Warn("Unknown EnableTCX value, defaulting to traditional TC attachment", zap.String("enableTCX", string(p.cfg.EnableTCX))) + } + return nil } @@ -423,14 +441,17 @@ func (p *packetParser) SetupChannel(ch chan *v1.Event) error { // cleanAll is NOT thread safe. // Not required for now. func (p *packetParser) cleanAll() error { - // Delete tunnel and qdiscs. - if p.tcMap == nil { + if p.attachmentMap == nil { return nil } - p.tcMap.Range(func(key, value interface{}) bool { - v := value.(*tcValue) - p.clean(v.tc, v.qdisc) + p.attachmentMap.Range(func(_, value interface{}) bool { + v := value.(*attachmentValue) + if v.attachmentType == attachmentTypeTCX { + p.cleanTCX(v.tcxIngressLink, v.tcxEgressLink) + } else { + p.clean(v.tc, v.qdisc) + } return true }) @@ -438,7 +459,7 @@ func (p *packetParser) cleanAll() error { // It is OK to do this without a lock because // cleanAll is only invoked from Stop(), and Stop can // only be called from PluginManager (which is single threaded). - p.tcMap = &sync.Map{} + p.attachmentMap = &sync.Map{} return nil } @@ -454,6 +475,55 @@ func (p *packetParser) clean(rtnl nltc, qdisc *tc.Object) { } } +// cleanTCX closes TCX links. This is best effort. +func (p *packetParser) cleanTCX(ingressLink, egressLink link.Link) { + if ingressLink != nil { + if err := ingressLink.Close(); err != nil { + p.l.Debug("could not close ingress TCX link", zap.Error(err)) + } + } + if egressLink != nil { + if err := egressLink.Close(); err != nil { + p.l.Debug("could not close egress TCX link", zap.Error(err)) + } + } +} + +// isTCXSupported probes whether the running kernel supports TCX attachment (kernel 6.6+) +// by creating a minimal BPF program and attempting to attach it to the loopback interface. +func isTCXSupported() bool { + loopback, err := netlink.LinkByName("lo") + if err != nil { + return false + } + + progSpec := &ebpf.ProgramSpec{ + Type: ebpf.SchedCLS, + AttachType: ebpf.AttachTCXIngress, + License: "Dual MIT/GPL", + Instructions: asm.Instructions{ + asm.Mov.Imm(asm.R0, -1), + asm.Return(), + }, + } + prog, err := ebpf.NewProgram(progSpec) + if err != nil { + return false + } + defer prog.Close() + + testLink, err := link.AttachTCX(link.TCXOptions{ + Program: prog, + Attach: ebpf.AttachTCXIngress, + Interface: loopback.Attrs().Index, + }) + if err != nil { + return false + } + testLink.Close() //nolint:errcheck // probe cleanup + return true +} + func (p *packetParser) endpointWatcherCallbackFn(obj interface{}) { // Contract is that we will receive an endpoint event pointer. event := obj.(*endpoint.EndpointEvent) @@ -476,11 +546,15 @@ func (p *packetParser) endpointWatcherCallbackFn(obj interface{}) { case endpoint.EndpointDeleted: p.l.Debug("Endpoint deleted", zap.String("name", iface.Name)) // Clean. - if value, ok := p.tcMap.Load(ifaceKey); ok { - v := value.(*tcValue) - p.clean(v.tc, v.qdisc) + if value, ok := p.attachmentMap.Load(ifaceKey); ok { + v := value.(*attachmentValue) + if v.attachmentType == attachmentTypeTCX { + p.cleanTCX(v.tcxIngressLink, v.tcxEgressLink) + } else { + p.clean(v.tc, v.qdisc) + } // Delete from map. - p.tcMap.Delete(ifaceKey) + p.attachmentMap.Delete(ifaceKey) } // Delete from lock map. p.interfaceLockMap.Delete(ifaceKey) @@ -490,9 +564,75 @@ func (p *packetParser) endpointWatcherCallbackFn(obj interface{}) { } } -// createQdiscAndAttach creates a qdisc of type clsact on the interface and attaches the ingress and egress bpf filter programs to it. +// createQdiscAndAttach attaches BPF ingress/egress programs to the interface using TCX or TC +// depending on kernel support and configuration. // Only support interfaces of type veth and device. func (p *packetParser) createQdiscAndAttach(iface netlink.LinkAttrs, ifaceType interfaceType) { + p.l.Debug("Starting attachment", zap.String("interface", iface.Name)) + + if p.tcxSupported { + p.attachViaTCX(iface, ifaceType) + return + } + + p.attachViaTC(iface, ifaceType) +} + +// attachViaTCX attaches BPF programs using TCX (TC eXpress, kernel 6.6+). +func (p *packetParser) attachViaTCX(iface netlink.LinkAttrs, ifaceType interfaceType) { + var ingressProgram, egressProgram *ebpf.Program + + switch ifaceType { + case Device: + ingressProgram = p.objs.HostIngressFilter + egressProgram = p.objs.HostEgressFilter + case Veth: + ingressProgram = p.objs.EndpointIngressFilter + egressProgram = p.objs.EndpointEgressFilter + default: + p.l.Error("Unknown interface type for TCX", zap.String("interface type", string(ifaceType))) + return + } + + // Attach at the head of the TCX chain so Retina sees every packet before + // any policy-enforcing program (e.g. Cilium) can drop it. This is safe + // because Retina's programs always return TC_ACT_UNSPEC, which passes + // control to the next program in the chain without making any forwarding + // decision. + ingressLink, err := link.AttachTCX(link.TCXOptions{ + Program: ingressProgram, + Attach: ebpf.AttachTCXIngress, + Interface: iface.Index, + Anchor: link.Head(), + }) + if err != nil { + p.l.Error("could not attach TCX ingress program", zap.String("interface", iface.Name), zap.Error(err)) + return + } + + egressLink, err := link.AttachTCX(link.TCXOptions{ + Program: egressProgram, + Attach: ebpf.AttachTCXEgress, + Interface: iface.Index, + Anchor: link.Head(), + }) + if err != nil { + p.l.Error("could not attach TCX egress program", zap.String("interface", iface.Name), zap.Error(err)) + ingressLink.Close() //nolint:errcheck // best effort + return + } + + ifaceKey := ifaceToKey(iface) + p.attachmentMap.Store(ifaceKey, &attachmentValue{ + attachmentType: attachmentTypeTCX, + tcxIngressLink: ingressLink, + tcxEgressLink: egressLink, + }) + p.l.Debug("Successfully attached BPF programs using TCX", zap.String("interface", iface.Name)) +} + +// attachViaTC attaches BPF programs using traditional TC with a clsact qdisc. +func (p *packetParser) attachViaTC(iface netlink.LinkAttrs, ifaceType interfaceType) { p.l.Debug("Starting qdisc attachment", zap.String("interface", iface.Name)) var ( @@ -513,7 +653,7 @@ func (p *packetParser) createQdiscAndAttach(iface netlink.LinkAttrs, ifaceType i ingressInfo = p.endpointIngressInfo egressInfo = p.endpointEgressInfo default: - p.l.Error("Unknown interface type", zap.String("interface type", string(ifaceType))) + p.l.Error("Unknown interface type for TC", zap.String("interface type", string(ifaceType))) return } @@ -601,13 +741,13 @@ func (p *packetParser) createQdiscAndAttach(iface netlink.LinkAttrs, ifaceType i // Cache. ifaceKey := ifaceToKey(iface) - tcValue := &tcValue{ - tc: rtnl, - qdisc: clsactQdisc, - } - p.tcMap.Store(ifaceKey, tcValue) + p.attachmentMap.Store(ifaceKey, &attachmentValue{ + attachmentType: attachmentTypeTC, + tc: rtnl, + qdisc: clsactQdisc, + }) - p.l.Debug("Successfully added bpf", zap.String("interface", iface.Name)) + p.l.Debug("Successfully attached BPF programs using traditional TC", zap.String("interface", iface.Name)) } func (p *packetParser) run(ctx context.Context) error { diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go index 4fa8b86aa0..311f31ea4e 100644 --- a/pkg/plugin/packetparser/packetparser_linux_test.go +++ b/pkg/plugin/packetparser/packetparser_linux_test.go @@ -97,7 +97,7 @@ func TestCleanAll(t *testing.T) { } assert.Nil(t, p.cleanAll()) - p.tcMap = &sync.Map{} + p.attachmentMap = &sync.Map{} assert.Nil(t, p.cleanAll()) ctrl := gomock.NewController(t) @@ -114,13 +114,13 @@ func TestCleanAll(t *testing.T) { return mq } - p.tcMap.Store(tcKey{"test", "test", 1}, &tcValue{mrtnl, &tc.Object{}}) - p.tcMap.Store(tcKey{"test2", "test2", 2}, &tcValue{mrtnl, &tc.Object{}}) + p.attachmentMap.Store(attachmentKey{"test", "test", 1}, &attachmentValue{tc: mrtnl, qdisc: &tc.Object{}}) + p.attachmentMap.Store(attachmentKey{"test2", "test2", 2}, &attachmentValue{tc: mrtnl, qdisc: &tc.Object{}}) assert.Nil(t, p.cleanAll()) keyCount := 0 - p.tcMap.Range(func(k, v interface{}) bool { + p.attachmentMap.Range(func(_ interface{}, _ interface{}) bool { keyCount++ return true }) @@ -196,7 +196,7 @@ func TestEndpointWatcherCallbackFn_EndpointDeleted(t *testing.T) { cfg: cfgPodLevelEnabled, l: log.Logger().Named("test"), interfaceLockMap: &sync.Map{}, - tcMap: &sync.Map{}, + attachmentMap: &sync.Map{}, } // Create test interface attributes. @@ -209,7 +209,7 @@ func TestEndpointWatcherCallbackFn_EndpointDeleted(t *testing.T) { // Pre-populate both maps to simulate existing interface p.interfaceLockMap.Store(key, &sync.Mutex{}) - p.tcMap.Store(key, &tcValue{nil, &tc.Object{}}) + p.attachmentMap.Store(key, &attachmentValue{tc: nil, qdisc: &tc.Object{}}) // Create EndpointDeleted event. e := &endpoint.EndpointEvent{ @@ -221,11 +221,10 @@ func TestEndpointWatcherCallbackFn_EndpointDeleted(t *testing.T) { p.endpointWatcherCallbackFn(e) // Verify both maps are cleaned up. - _, tcMapExists := p.tcMap.Load(key) + _, attachmentMapExists := p.attachmentMap.Load(key) _, lockMapExists := p.interfaceLockMap.Load(key) - // Assert both maps are cleaned up - assert.False(t, tcMapExists, "tcMap entry should be deleted") + assert.False(t, attachmentMapExists, "attachmentMap entry should be deleted") assert.False(t, lockMapExists, "interfaceLockMap entry should be deleted") } @@ -256,7 +255,7 @@ func TestCreateQdiscAndAttach(t *testing.T) { return mrtnl, nil } - getFD = func(e *ebpf.Program) int { + getFD = func(_ *ebpf.Program) int { return 1 } @@ -281,7 +280,7 @@ func TestCreateQdiscAndAttach(t *testing.T) { hostEgressInfo: &ebpf.ProgramInfo{ Name: "egress", }, - tcMap: &sync.Map{}, + attachmentMap: &sync.Map{}, } linkAttr := netlink.LinkAttrs{ Name: "test", @@ -292,7 +291,7 @@ func TestCreateQdiscAndAttach(t *testing.T) { p.createQdiscAndAttach(linkAttr, Veth) key := ifaceToKey(linkAttr) - _, ok := p.tcMap.Load(key) + _, ok := p.attachmentMap.Load(key) assert.True(t, ok) pObj.HostIngressFilter = &ebpf.Program{} @@ -306,7 +305,7 @@ func TestCreateQdiscAndAttach(t *testing.T) { p.createQdiscAndAttach(linkAttr2, Device) key = ifaceToKey(linkAttr2) - _, ok = p.tcMap.Load(key) + _, ok = p.attachmentMap.Load(key) assert.True(t, ok) } @@ -476,7 +475,7 @@ func TestStartWithDataAggregationLevelLow(t *testing.T) { hostEgressInfo: &ebpf.ProgramInfo{ Name: "egress", }, - tcMap: &sync.Map{}, + attachmentMap: &sync.Map{}, } ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() @@ -555,7 +554,7 @@ func TestStartWithDataAggregationLevelHigh(t *testing.T) { hostEgressInfo: &ebpf.ProgramInfo{ Name: "egress", }, - tcMap: &sync.Map{}, + attachmentMap: &sync.Map{}, } ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() diff --git a/pkg/plugin/packetparser/types_linux.go b/pkg/plugin/packetparser/types_linux.go index a968b910ad..fa7f7d78ee 100644 --- a/pkg/plugin/packetparser/types_linux.go +++ b/pkg/plugin/packetparser/types_linux.go @@ -10,6 +10,7 @@ import ( v1 "github.com/cilium/cilium/pkg/hubble/api/v1" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/link" tc "github.com/florianl/go-tc" nl "github.com/mdlayher/netlink" "github.com/vishvananda/netlink" @@ -74,15 +75,30 @@ var ( perCPUBuffer = 32 ) -type tcKey struct { +// attachmentKey uniquely identifies a network interface for BPF program attachment. +type attachmentKey struct { name string hardwareAddr string netNs int } -type tcValue struct { +// attachmentType represents the method used to attach BPF programs. +type attachmentType int + +const ( + attachmentTypeTC attachmentType = iota // Traditional TC with clsact qdisc + attachmentTypeTCX // TCX (TC eXpress) - kernel 6.6+ +) + +// attachmentValue stores the attachment details for a network interface. +type attachmentValue struct { + // TC-specific fields tc nltc qdisc *tc.Object + // TCX-specific fields + attachmentType attachmentType + tcxIngressLink link.Link + tcxEgressLink link.Link } //go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types_linux.go -package=mocks @@ -123,10 +139,10 @@ type packetParser struct { l *log.ZapLogger callbackID string objs *packetparserObjects //nolint:typecheck - // tcMap is a map of key to *val. - tcMap *sync.Map - reader perfReader - enricher enricher.EnricherInterface + // attachmentMap is a map of interface key to attachment details (TC or TCX). + attachmentMap *sync.Map + reader perfReader + enricher enricher.EnricherInterface // interfaceLockMap is a map of key to *sync.Mutex. interfaceLockMap *sync.Map endpointIngressInfo *ebpf.ProgramInfo @@ -136,10 +152,11 @@ type packetParser struct { wg sync.WaitGroup recordsChannel chan perfRecord externalChannel chan *v1.Event + tcxSupported bool // Whether TCX is supported on this system } -func ifaceToKey(iface netlink.LinkAttrs) tcKey { - return tcKey{ +func ifaceToKey(iface netlink.LinkAttrs) attachmentKey { + return attachmentKey{ name: iface.Name, hardwareAddr: iface.HardwareAddr.String(), netNs: iface.NetNsID, From abc216b6eecae1dad7686011d9c2c31a9176352b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:37:32 -0400 Subject: [PATCH 256/448] deps: bump github/codeql-action from 4.33.0 to 4.34.0 (#2126) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.33.0 to 4.34.0.
Release notes

Sourced from github/codeql-action's releases.

v4.34.0

  • Added an experimental change which disables TRAP caching when improved incremental analysis is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. #3569
  • We are rolling out improved incremental analysis to C/C++ analyses that use build mode none. We expect this rollout to be complete by the end of April 2026. #3584
  • Update default CodeQL bundle version to 2.25.0. #3585
Commits
  • c6f9311 Merge pull request #3588 from github/update-v4.34.0-30c555a52
  • eeb9b3f Update changelog for v4.34.0
  • 30c555a Merge pull request #3584 from github/idrissrio/cpp/overlay
  • 39191bd Merge branch 'main' into idrissrio/cpp/overlay
  • 147e93e Merge pull request #3585 from github/update-bundle/codeql-bundle-v2.25.0
  • e6d83bc Update CHANGELOG.md
  • 0d057cc Add changelog note for C/C++ overlay
  • 074a0db Feature flag: update test without overlay support
  • ab3b6fd Feature flag: address copilot comment
  • ce4a1fe Feature flag: update generated lib after build
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.33.0&new-version=4.34.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index e07cc9b365..1cafa9abc4 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 + uses: github/codeql-action/init@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 + uses: github/codeql-action/autobuild@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 + uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index d5f88b0183..42e7001afd 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 + uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: sarif_file: "trivy-results.sarif" From 7a5852de1972f85e2297a51eb1f5152679792b88 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 19:54:52 +0000 Subject: [PATCH 257/448] fix(helm): replace retina.io with retina.sh in hubble ClusterRole templates (#2100) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Hubble Helm ClusterRole templates still reference the old `retina.io` API group, while CRDs moved to `retina.sh` in PR #26. This causes the agent and operator to lack permissions for their own custom resources, crashing on launch. Replaces all 8 occurrences of `retina.io` with `retina.sh`: - **`templates/agent/clusterrole.yaml`** (5 occurrences): `retinaendpoints`, `metricsconfigurations`, `retinaendpoints/finalizers`, `retinaendpoints/status` - **`templates/operator/clusterrole.yaml`** (3 occurrences): `captures`, `captures/finalizers`, `captures/status` The standard (non-hubble) variant already uses the correct API group. ## Related Issue Hubble-deployed agent crashes because `retina-agent` service account cannot list `metricsconfigurations.retina.sh` or `captures.retina.sh` — the ClusterRoles grant access to the nonexistent `retina.io` group instead. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Verified no `retina.io` references remain anywhere under `deploy/`. Diff is a pure string replacement with no structural changes. ## Additional Notes None. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project.
Original prompt ---- *This section details on the original issue you should resolve* Helm-deployed agent crashing on launch: Helm-deployed ClusterRoles for operator, agent etc still use retina.io instead of retina.sh **Describe the bug** Service account in `kube-system`, `retina-agent`, seemingly has no permissions to list Retina's own CRs defined as being in `retina.sh` namespace. **EDIT** Below, `retina-agent-init` is actually running the operator image instead of the init. My bad! **The apigroups are, nonetheless, wrong.** Here's an excerpt from `retina-agent-init` container of the `retina-agent-*` pod (it never reaches the `retina-agent` container): ``` [EDIT] This is from the retina-operator image, by accident. The bug still applies. E1118 23:39:21.428138 1 reflector.go:166] "Unhandled Error" err="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v1alpha1.MetricsConfiguration: failed to list *v1alpha1.MetricsConfiguration: metricsconfigurations.retina.sh is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"metricsconfigurations\" in API group \"retina.sh\" at the cluster scope" logger="UnhandledError" W1118 23:39:22.001828 1 reflector.go:569] pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v1alpha1.Capture: captures.retina.sh is forbidden: User "system:serviceaccount:kube-system:retina-agent" cannot list resource "captures" in API group "retina.sh" at the cluster scope E1118 23:39:22.001924 1 reflector.go:166] "Unhandled Error" err="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v1alpha1.Capture: failed to list *v1alpha1.Capture: captures.retina.sh is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"captures\" in API group \"retina.sh\" at the cluster scope" logger="UnhandledError" W1118 23:39:24.764710 1 reflector.go:569] pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v1.Job: jobs.batch is forbidden: User "system:serviceaccount:kube-system:retina-agent" cannot list resource "jobs" in API group "batch" at the cluster scope E1118 23:39:24.765201 1 reflector.go:166] "Unhandled Error" err="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v1.Job: failed to list *v1.Job: jobs.batch is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"jobs\" in API group \"batch\" at the cluster scope" logger="UnhandledError" W1118 23:39:26.796528 1 reflector.go:569] pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v1alpha1.MetricsConfiguration: metricsconfigurations.retina.sh is forbidden: User "system:serviceaccount:kube-system:retina-agent" cannot list resource "metricsconfigurations" in API group "retina.sh" at the cluster scope E1118 23:39:26.796687 1 reflector.go:166] "Unhandled Error" err="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v1alpha1.MetricsConfiguration: failed to list *v1alpha1.MetricsConfiguration: metricsconfigurations.retina.sh is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"metricsconfigurations\" in API group \"retina.sh\" at the cluster scope" logger="UnhandledError" W1118 23:39:26.887540 1 reflector.go:569] pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: failed to list *v1alpha1.Capture: captures.retina.sh is forbidden: User "system:serviceaccount:kube-system:retina-agent" cannot list resource "captures" in API group "retina.sh" at the cluster scope E1118 23:39:26.888200 1 reflector.go:166] "Unhandled Error" err="pkg/mod/k8s.io/client-go@v0.32.4/tools/cache/reflector.go:251: Failed to watch *v1alpha1.Capture: failed to list *v1alpha1.Capture: captures.retina.sh is forbidden: User \"system:serviceaccount:kube-system:retina-agent\" cannot list resource \"captures\" in API group \"retina.sh\" at the cluster scope" logger="UnhandledError" ``` This error is similar to microsoft/retina#1122, but actually unrelated. Examining the relevant `ClusterRole` object, `retina-cluster-reader`, I can see that in multiple places it seems to reference `retina.io` which is gone since pull request microsoft/retina#26 which replaced `retina.io` with `retina.sh` in most places: https://github.com/microsoft/retina/blob/f5255405758db24b25f6bb4a31e3ee14f0b4e955/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml#L17-L24 https://github.com/microsoft/retina/blob/f5255405758db24b25f6bb4a31e3ee14f0b4e955/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml#L45-L82 This is also happening in the operator `ClusterRole` object, `retina-operator-role`: https://github.com/microsoft/retina/blob/f2da04b8bbe1a3b232c2af2987b2f87051392a34/deploy/hubble/manifests/controller/helm/retina/templat...
- Fixes microsoft/retina#1936 --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). Signed-off-by: Quang Nguyen Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Quang Nguyen --- .../helm/retina/templates/agent/clusterrole.yaml | 10 +++++----- .../helm/retina/templates/operator/clusterrole.yaml | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml index e2331c5d9f..ab71f1d7a6 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml @@ -15,7 +15,7 @@ rules: resources: ["clusterobservers"] verbs: ["get", "list", "watch"] - apiGroups: - - retina.io + - retina.sh resources: - retinaendpoints verbs: @@ -43,7 +43,7 @@ rules: - watch {{- if .Values.operator.enabled }} - apiGroups: - - retina.io + - retina.sh resources: - retinaendpoints verbs: @@ -55,7 +55,7 @@ rules: - update - watch - apiGroups: - - retina.io + - retina.sh resources: - metricsconfigurations verbs: @@ -67,13 +67,13 @@ rules: - update - watch - apiGroups: - - retina.io + - retina.sh resources: - retinaendpoints/finalizers verbs: - update - apiGroups: - - retina.io + - retina.sh resources: - retinaendpoints/status verbs: diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml index 3e436490f9..395bb0bb2f 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml @@ -52,7 +52,7 @@ rules: verbs: - get - apiGroups: - - retina.io + - retina.sh resources: - captures verbs: @@ -64,13 +64,13 @@ rules: - update - watch - apiGroups: - - retina.io + - retina.sh resources: - captures/finalizers verbs: - update - apiGroups: - - retina.io + - retina.sh resources: - captures/status verbs: From 7c589a718e9ef7192fa9f6c17c58774b0b7f6f36 Mon Sep 17 00:00:00 2001 From: Uudit Misra Date: Fri, 20 Mar 2026 13:23:12 -0700 Subject: [PATCH 258/448] fix: add guard clause for MetricsInterval (#2084) Prevent panic: runtime error: invalid duration when MetricsInterval is missing or set to 0. Added a default fallback to 10s and a warning log to inform the user of the configuration issue. Closes #2029 # Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Uudit Misra --- .../controller/helm/retina/values.yaml | 2 + .../controller/helm/retina/values.yaml | 2 + pkg/managers/pluginmanager/pluginmanager.go | 7 ++- .../pluginmanager/pluginmanager_test.go | 62 ++++++++++++++++++- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 0dd54b5200..10954f56dd 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -109,6 +109,8 @@ enableTCX: "auto" enableTelemetry: false # Interval, in duration, to scrape/publish metrics. +# Default when unset or invalid (used by pluginmanager and all plugins). +metricsInterval: "10s" metricsIntervalDuration: "10s" azure: diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index 4323c23f64..76e1c7c758 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -100,6 +100,8 @@ enabledPlugin_win: '["hnsstats"]' enableTelemetry: false # Interval, in duration, to scrape/publish metrics. +# Default when unset or invalid (used by pluginmanager and all plugins). +metricsInterval: "10s" metricsIntervalDuration: "10s" azure: diff --git a/pkg/managers/pluginmanager/pluginmanager.go b/pkg/managers/pluginmanager/pluginmanager.go index cbb5619e59..f3d3ad5348 100644 --- a/pkg/managers/pluginmanager/pluginmanager.go +++ b/pkg/managers/pluginmanager/pluginmanager.go @@ -22,6 +22,8 @@ import ( ) const ( + // DefaultMetricsInterval is used when MetricsInterval is zero or negative. + DefaultMetricsInterval = 10 * time.Second // In any run I haven't seen reconcile take longer than 5 seconds, // and 10 seconds seems like a reasonable SLA for reconciliation to be completed @@ -126,8 +128,9 @@ func (p *PluginManager) Start(ctx context.Context) error { return ErrNilCfg } - if p.cfg.MetricsInterval == 0 { - return ErrZeroInterval + if p.cfg.MetricsInterval <= 0 { + p.l.Warn("MetricsInterval is invalid or unset; defaulting to 10s", zap.Duration("interval", p.cfg.MetricsInterval)) + p.cfg.MetricsInterval = DefaultMetricsInterval } if p.cfg.EnablePodLevel { diff --git a/pkg/managers/pluginmanager/pluginmanager_test.go b/pkg/managers/pluginmanager/pluginmanager_test.go index 2203468b5b..036cfc69c7 100644 --- a/pkg/managers/pluginmanager/pluginmanager_test.go +++ b/pkg/managers/pluginmanager/pluginmanager_test.go @@ -24,7 +24,8 @@ import ( ) const ( - timeInter = time.Second * 10 + timeInter = time.Second * 10 + mockPluginName = "mockplugin" ) var ( @@ -151,6 +152,65 @@ func TestNewManagerStart(t *testing.T) { } } +func TestStart_InvalidMetricsIntervalDefaultsTo10s(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + + tests := []struct { + name string + interval time.Duration + }{ + {"zero interval", 0}, + {"negative interval", -1 * time.Second}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctl := gomock.NewController(t) + defer ctl.Finish() + + cfg := cfgPodLevelDisabled + cfg.MetricsInterval = tt.interval + cfg.EnabledPlugin = append(cfg.EnabledPlugin, mockPluginName) + + mgr, err := NewPluginManager(&cfg, telemetry.NewNoopTelemetry()) + require.NoError(t, err) + require.NotNil(t, mgr) + mgr.watcherManager = setupWatcherManagerMock(ctl) + + mockPlugin := pluginmock.NewMockPlugin(ctl) + mockPlugin.EXPECT().Generate(gomock.Any()).Return(nil).AnyTimes() + mockPlugin.EXPECT().Compile(gomock.Any()).Return(nil).AnyTimes() + mockPlugin.EXPECT().Stop().Return(nil).AnyTimes() + mockPlugin.EXPECT().Init().Return(nil).AnyTimes() + mockPlugin.EXPECT().Start(gomock.Any()).Return(nil).AnyTimes() + mockPlugin.EXPECT().Name().Return(mockPluginName).AnyTimes() + mgr.plugins[mockPluginName] = mockPlugin + + ctx, cancel := context.WithCancel(context.Background()) + done := make(chan error, 1) + go func() { + done <- mgr.Start(ctx) + }() + + // Give Start() time to apply the default + time.Sleep(100 * time.Millisecond) + require.Equal(t, DefaultMetricsInterval, mgr.cfg.MetricsInterval, + "MetricsInterval should be defaulted to DefaultMetricsInterval") + + cancel() + // Start returns when context is cancelled (plugins exit) + err = <-done + if err != nil { + // Ignore conntrack-related errors in this test + if !strings.Contains(err.Error(), "failed to get conntrack instance") && + !strings.Contains(err.Error(), "failed to run conntrack GC") { + require.NoError(t, err) + } + } + }) + } +} + func TestNewManagerWithPluginStartFailure(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() From 71bf4974249932ae56c5fe613d2f467bfecdb117 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 17:24:42 -0400 Subject: [PATCH 259/448] fix(ci): gate krew-release-bot on final release tags only (#2107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `krew-release-bot` step was triggering on all tag pushes (`v*`), including pre-release tags like `v1.0.0-alpha.1` and `v1.0.0-rc.1`, spamming [krew-index](https://github.com/kubernetes-sigs/krew-index) with spurious PRs. # Description **`.github/workflows/goreleaser.yaml`**: Added a "Check if release tag" step that uses bash to match the tag against the regex `^v[0-9]+\.[0-9]+\.[0-9]+$` and sets a step output. The krew-release-bot step is then gated on that output, so it only runs on final release tags and skips pre-release tags. ```yaml - name: Check if release tag id: check-tag run: | if [[ "${{ github.ref_name }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "is_release=true" >> $GITHUB_OUTPUT else echo "is_release=false" >> $GITHUB_OUTPUT fi - name: Update new version in krew-index if: github.repository_owner == 'microsoft' && steps.check-tag.outputs.is_release == 'true' uses: rajatjindal/krew-release-bot@... ``` GitHub Actions expressions do not support regex natively, so a dedicated bash step is used to perform the regex match and expose the result as a step output. This does not affect the rest of the `release` job (binary builds, GoReleaser, etc.), which will continue to run on all tag pushes. ## Related Issue Resolves the krew-index spam reported in the issue. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed N/A — workflow-only change; can be validated by pushing a pre-release tag and confirming the krew step is skipped. ## Additional Notes This does not affect the rest of the `release` job (binary builds, GoReleaser, etc.), which will continue to run on all tag pushes.
Original prompt > > ---- > > *This section details on the original issue you should resolve* > > Do not run krew-release action on pre-releases > This repo is spamming krew-index with PRs like https://github.com/kubernetes-sigs/krew-index/pull/4933 > > Please only run this action on tag `v[0-9]+\.[0-9]+\.[0-9]+$'`. > > cc: @matmerr > > ## Comments on the Issue (you are @copilot in this section) > > > >
- Fixes microsoft/retina#2106 --- 🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. [Learn more about Advanced Security.](https://gh.io/cca-advanced-security) Signed-off-by: Quang Nguyen Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Quang Nguyen --- .github/workflows/goreleaser.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 1265e0ab6d..4e521a7586 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -63,6 +63,14 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent + - name: Check if release tag + id: check-tag + run: | + if [[ "${{ github.ref_name }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "is_release=true" >> $GITHUB_OUTPUT + else + echo "is_release=false" >> $GITHUB_OUTPUT + fi - name: Update new version in krew-index - if: github.repository_owner == 'microsoft' + if: github.repository_owner == 'microsoft' && steps.check-tag.outputs.is_release == 'true' uses: rajatjindal/krew-release-bot@c970b8a8f6dbc2f2285a26e3ae160903b87002c3 # v0.0.51 From 2960dc61d8d701d7c6a7f7d02d926df5ad04b1cc Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Mon, 23 Mar 2026 12:10:37 +0000 Subject: [PATCH 260/448] docs: Add redirect from /docs/intro to Introduction page (#2127) Install @docusaurus/plugin-client-redirects and configure redirects from /docs/intro and /intro to /docs/Introduction/intro. # Description Please provide a brief This pull request introduces support for client-side redirects in the Docusaurus documentation site and makes several related dependency updates. The main focus is on improving the user experience by ensuring old or alternative documentation URLs correctly redirect to the new structure. Additionally, the pull request updates package dependencies and lockfiles to include the new plugin and mark several dependencies as peer dependencies. **Documentation site enhancements:** * Added the `@docusaurus/plugin-client-redirects` plugin to the project dependencies and configuration, enabling client-side redirects in the documentation site. [[1]](diffhunk://#diff-35f15d66f9b39b506a11ac9b5c6b9a80e11b41bfd56832ab130372902258ccf7R18) [[2]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR12) [[3]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR3690-R3713) * Configured redirects so that requests to `/docs/intro` or `/intro` are automatically redirected to `/docs/Introduction/intro`. **Dependency and lockfile updates:** * Updated `package-lock.json` to include `@docusaurus/plugin-client-redirects` and mark several dependencies as peer dependencies for better compatibility and dependency management. [[1]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR12) [[2]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR173) [[3]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR299) [[4]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2104) [[5]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2127) [[6]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2237) [[7]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2659) [[8]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR3494) [[9]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR3753) [[10]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR4866) [[11]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5166) [[12]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5532) [[13]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5877) [[14]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5944) [[15]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5990) [[16]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR6600) [[17]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR7620) [[18]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR9141) [[19]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR13770) [[20]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR14345) [[21]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR15219) [[22]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR16092) [[23]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR16105) [[24]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR16158) [[25]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR16185) [[26]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR17337) [[27]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fL18228-R18279) [[28]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR18351) [[29]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR18707) [[30]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR18903) **Documentation metadata:** * Added frontmatter to `docs/01-Introduction/01-intro.md` to set the slug for the introduction page, aligning it with the new redirect target. description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- docs/01-Introduction/01-intro.md | 4 +++ site/docusaurus.config.ts | 11 +++++++ site/package-lock.json | 56 +++++++++++++++++++++++++++++++- site/package.json | 1 + 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/docs/01-Introduction/01-intro.md b/docs/01-Introduction/01-intro.md index bdff1241af..8ffab06297 100644 --- a/docs/01-Introduction/01-intro.md +++ b/docs/01-Introduction/01-intro.md @@ -1,3 +1,7 @@ +--- +slug: /Introduction/intro +--- + # What is Retina? ## Introduction diff --git a/site/docusaurus.config.ts b/site/docusaurus.config.ts index 4c1e8a04cf..3fdbc12587 100644 --- a/site/docusaurus.config.ts +++ b/site/docusaurus.config.ts @@ -28,6 +28,17 @@ const config = { plugins: [ "docusaurus-lunr-search", + [ + "@docusaurus/plugin-client-redirects", + { + redirects: [ + { + from: ["/docs/intro", "/intro"], + to: "/docs/Introduction/intro", + }, + ], + }, + ], [ "@docusaurus/plugin-ideal-image", { diff --git a/site/package-lock.json b/site/package-lock.json index 45f5abfbb0..4594b21ac3 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@docusaurus/core": "^3.9.2", + "@docusaurus/plugin-client-redirects": "^3.9.2", "@docusaurus/plugin-ideal-image": "^3.9.2", "@docusaurus/preset-classic": "^3.9.2", "@mdx-js/react": "^3.1.1", @@ -169,6 +170,7 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-common": "5.48.1", "@algolia/requester-browser-xhr": "5.48.1", @@ -294,6 +296,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2098,6 +2101,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2120,6 +2124,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2229,6 +2234,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2650,6 +2656,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3484,6 +3491,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/babel": "3.9.2", "@docusaurus/bundler": "3.9.2", @@ -3679,6 +3687,30 @@ "react-dom": "*" } }, + "node_modules/@docusaurus/plugin-client-redirects": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.9.2.tgz", + "integrity": "sha512-lUgMArI9vyOYMzLRBUILcg9vcPTCyyI2aiuXq/4npcMVqOr6GfmwtmBYWSbNMlIUM0147smm4WhpXD0KFboffw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/plugin-content-blog": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz", @@ -3718,6 +3750,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/logger": "3.9.2", @@ -4830,6 +4863,7 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5129,6 +5163,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5494,6 +5529,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -5838,6 +5874,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5904,6 +5941,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5949,6 +5987,7 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/abtesting": "1.14.1", "@algolia/client-abtesting": "5.48.1", @@ -6558,6 +6597,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7577,6 +7617,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9097,6 +9138,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13725,6 +13767,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14299,6 +14342,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15172,6 +15216,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -16044,6 +16089,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16056,6 +16102,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -16108,6 +16155,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -16134,6 +16182,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17285,6 +17334,7 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, + "peer": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -18225,7 +18275,8 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "peer": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18297,6 +18348,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18652,6 +18704,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18847,6 +18900,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", diff --git a/site/package.json b/site/package.json index f9bbc20968..111dbeeb26 100644 --- a/site/package.json +++ b/site/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@docusaurus/core": "^3.9.2", + "@docusaurus/plugin-client-redirects": "^3.9.2", "@docusaurus/plugin-ideal-image": "^3.9.2", "@docusaurus/preset-classic": "^3.9.2", "@mdx-js/react": "^3.1.1", From a201ae7aeb27906cb176fe9deae87231f7ab06aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 10:38:37 -0400 Subject: [PATCH 261/448] deps: bump anchore/sbom-action from 0.23.1 to 0.24.0 (#2130) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.23.1 to 0.24.0.
Release notes

Sourced from anchore/sbom-action's releases.

v0.24.0

⬆️ Dependencies

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anchore/sbom-action&package-manager=github_actions&previous-version=0.23.1&new-version=0.24.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 4e521a7586..7cf9cd4bb5 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -29,7 +29,7 @@ jobs: with: go-version-file: go.mod - name: Install Syft - uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1 + uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser build uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 env: @@ -53,7 +53,7 @@ jobs: with: go-version-file: go.mod - name: Install Syft - uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1 + uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser release uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 with: From 4b39400afbccdd78b17722ff508378ce431dcef9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:41:41 -0400 Subject: [PATCH 262/448] deps: bump github/codeql-action from 4.34.0 to 4.34.1 (#2129) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.34.0 to 4.34.1.
Release notes

Sourced from github/codeql-action's releases.

v4.34.1

  • Downgrade default CodeQL bundle version to 2.24.3 due to issues with a small percentage of Actions and JavaScript analyses. #3762
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.34.1 - 20 Mar 2026

  • Downgrade default CodeQL bundle version to 2.24.3 due to issues with a small percentage of Actions and JavaScript analyses. #3762

4.34.0 - 20 Mar 2026

  • Added an experimental change which disables TRAP caching when improved incremental analysis is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. #3569
  • We are rolling out improved incremental analysis to C/C++ analyses that use build mode none. We expect this rollout to be complete by the end of April 2026. #3584
  • Update default CodeQL bundle version to 2.25.0. #3585

4.33.0 - 16 Mar 2026

  • Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. #3562

    To opt out of this change:

    • Repositories owned by an organization: Create a custom repository property with the name github-codeql-file-coverage-on-prs and the type "True/false", then set this property to true in the repository's settings. For more information, see Managing custom properties for repositories in your organization. Alternatively, if you are using an advanced setup workflow, you can set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using default setup: Switch to an advanced setup workflow and set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using advanced setup: Set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
  • Fixed a bug which caused the CodeQL Action to fail loading repository properties if a "Multi select" repository property was configured for the repository. #3557

  • The CodeQL Action now loads custom repository properties on GitHub Enterprise Server, enabling the customization of features such as github-codeql-disable-overlay that was previously only available on GitHub.com. #3559

  • Once private package registries can be configured with OIDC-based authentication for organizations, the CodeQL Action will now be able to accept such configurations. #3563

  • Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". #3564

  • A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. #3570

4.32.6 - 05 Mar 2026

  • Update default CodeQL bundle version to 2.24.3. #3548

4.32.5 - 02 Mar 2026

  • Repositories owned by an organization can now set up the github-codeql-disable-overlay custom repository property to disable improved incremental analysis for CodeQL. First, create a custom repository property with the name github-codeql-disable-overlay and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to true to disable improved incremental analysis. For more information, see Managing custom properties for repositories in your organization. This feature is not yet available on GitHub Enterprise Server. #3507
  • Added an experimental change so that when improved incremental analysis fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. #3487
  • The minimum memory check for improved incremental analysis is now skipped for CodeQL 2.24.3 and later, which has reduced peak RAM usage. #3515
  • Reduced log levels for best-effort private package registry connection check failures to reduce noise from workflow annotations. #3516
  • Added an experimental change which lowers the minimum disk space requirement for improved incremental analysis, enabling it to run on standard GitHub Actions runners. We expect to roll this change out to everyone in March. #3498
  • Added an experimental change which allows the start-proxy action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. #3512
  • The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. #3503, #3504

4.32.4 - 20 Feb 2026

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473

... (truncated)

Commits
  • 3869755 Merge pull request #3763 from github/update-v4.34.1-095e0fe50
  • 20e68ac Update changelog for v4.34.1
  • 095e0fe Merge pull request #3762 from github/henrymercer/downgrade-default-bundle
  • 47b94fe Add changelog note
  • 51a1d69 Downgrade default bundle to codeql-bundle-v2.24.3
  • 510cf73 Merge pull request #3589 from github/mergeback/v4.34.0-to-main-c6f93110
  • 89f0c86 Rebuild
  • c3f90ba Update changelog and version after v4.34.0
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.34.0&new-version=4.34.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 1cafa9abc4..6263c5c417 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 42e7001afd..5ec05e02e9 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: sarif_file: "trivy-results.sarif" From fa3107dbebc734bef56cfe7ed079965a81bff415 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 25 Mar 2026 15:23:50 -0400 Subject: [PATCH 263/448] fix(e2e): update VM SKUs and remove hardcoded availability zones (#2132) ## Description E2E and scale test runs are failing due to previous-generation, capacity-limited VM SKUs that are no longer reliably available in eastus2 ([example failed run](https://github.com/microsoft/retina/actions/runs/23519538032)). These SKUs are listed as [previous-generation with retirement announced](https://learn.microsoft.com/en-us/azure/virtual-machines/sizes/previous-gen-sizes-list). This PR: - Replaces `Standard_DS4_v2` with `Standard_D4s_v6` (current-gen Dsv6 series) - Adds `Standard_D4s_v5` for Windows 2022 node pool (Dsv6 is Gen 2 only; WS2022 on AKS defaults to Gen 1) - Replaces `Standard_D4pls_v5` with `Standard_D4pls_v6` (current-gen ARM Dpsv6 series) - Replaces `Standard_D4_v3` with `Standard_D4s_v6` in scale tests - Removes hardcoded availability zone assignments from all node pools ## Related Issue Fixes merge queue E2E failures due to capacity-limited SKUs in eastus2. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed E2E cluster creation should now succeed in eastus2 without `AvailabilityZoneNotSupported` or SKU compatibility errors. Signed-off-by: Quang Nguyen --- test/e2e/framework/azure/create-cluster-with-npm.go | 11 ++++------- test/e2e/framework/azure/create-cluster.go | 6 +++--- test/e2e/jobs/scale.go | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index fce22b9a91..76b94348e0 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -21,7 +21,7 @@ const ( clusterTimeout = 15 * time.Minute clusterCreateTicker = 30 * time.Second pollFrequency = 5 * time.Second - AgentARMSKU = "Standard_D4pls_v5" + AgentARMSKU = "Standard_D4pls_v6" AuxilaryNodeCount = 1 AuxilaryARMNodeCount = 2 ) @@ -55,15 +55,14 @@ func (c *CreateNPMCluster) Run() error { //nolint:appendCombine // separate for verbosity npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ //nolint:all - Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), - // AvailabilityZones: []*string{to.Ptr("1")}, + Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), Count: to.Ptr[int32](AuxilaryNodeCount), EnableNodePublicIP: to.Ptr(false), Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), OSType: to.Ptr(armcontainerservice.OSTypeWindows), OSSKU: to.Ptr(armcontainerservice.OSSKUWindows2022), ScaleDownMode: to.Ptr(armcontainerservice.ScaleDownModeDelete), - VMSize: to.Ptr(AgentSKU), + VMSize: to.Ptr(AgentWindowsSKU), Name: to.Ptr("ws22"), MaxPods: to.Ptr(int32(MaxPodsPerNode)), }) @@ -71,7 +70,6 @@ func (c *CreateNPMCluster) Run() error { //nolint:appendCombine // separate for verbosity npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), - AvailabilityZones: []*string{to.Ptr("1")}, Count: to.Ptr[int32](AuxilaryNodeCount), EnableNodePublicIP: to.Ptr(false), EnableFIPS: to.Ptr(true), @@ -86,8 +84,7 @@ func (c *CreateNPMCluster) Run() error { //nolint:appendCombine // separate for verbosity npmCluster.Properties.AgentPoolProfiles = append(npmCluster.Properties.AgentPoolProfiles, &armcontainerservice.ManagedClusterAgentPoolProfile{ //nolint:all - Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), - // AvailabilityZones: []*string{to.Ptr("1")}, + Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), Count: to.Ptr[int32](AuxilaryARMNodeCount), EnableNodePublicIP: to.Ptr(false), Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), diff --git a/test/e2e/framework/azure/create-cluster.go b/test/e2e/framework/azure/create-cluster.go index c6a5b9e50a..3709b2145e 100644 --- a/test/e2e/framework/azure/create-cluster.go +++ b/test/e2e/framework/azure/create-cluster.go @@ -14,7 +14,8 @@ import ( const ( MaxNumberOfNodes = 3 MaxPodsPerNode = 250 - AgentSKU = "Standard_DS4_v2" + AgentSKU = "Standard_D4s_v6" + AgentWindowsSKU = "Standard_D4s_v4" ) var defaultClusterCreateTimeout = 30 * time.Minute @@ -110,8 +111,7 @@ func GetStarterClusterTemplate(location string) armcontainerservice.ManagedClust */ AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{ { - Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), - // AvailabilityZones: []*string{to.Ptr("1")}, + Type: to.Ptr(armcontainerservice.AgentPoolTypeVirtualMachineScaleSets), Count: to.Ptr[int32](MaxNumberOfNodes), EnableNodePublicIP: to.Ptr(false), Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem), diff --git a/test/e2e/jobs/scale.go b/test/e2e/jobs/scale.go index f4c8ac7d9a..0b27feb4a3 100644 --- a/test/e2e/jobs/scale.go +++ b/test/e2e/jobs/scale.go @@ -62,7 +62,7 @@ func GetScaleTestInfra(subID, rg, clusterName, location, kubeConfigFilePath stri Nodes: nodes, }). SetPodCidr("100.64.0.0/10"). - SetVMSize("Standard_D4_v3"). + SetVMSize("Standard_D4s_v6"). SetNetworkPluginMode("overlay"), nil) job.AddStep(&azure.GetAKSKubeConfig{ From b13b44f4650aa5db931c7fa68712eb68e502617c Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 25 Mar 2026 16:37:57 -0400 Subject: [PATCH 264/448] fix(ci): ensure Docker daemon is ready on Windows 2022 runners (#2124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description The "Build Agent Image - Windows 2022" job intermittently fails with: ``` failed to connect to the docker API at npipe:////./pipe/docker_engine; open //./pipe/docker_engine: The system cannot find the file specified. ``` Unlike Linux runners where Docker is managed by systemd and always available, Windows runners start Docker Engine as a Windows Service that can be slow to initialize or sometimes not running at job start. Add a Docker daemon readiness step that polls `docker info` with a 2-minute timeout, attempting to start the service if it's not running. ## Related Issue N/A — fixing flaky CI observed across multiple recent runs. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI will validate — the Docker readiness step itself will be exercised on the next `windows-2022` run. Recent failures with the same root cause: - https://github.com/microsoft/retina/actions/runs/23272086310 (merge_group, failed at `az acr login`) - https://github.com/microsoft/retina/actions/runs/23205238449 (merge_group, failed at `az acr login`) - https://github.com/microsoft/retina/actions/runs/23199469940 (pull_request, failed at `docker build`) - https://github.com/microsoft/retina/actions/runs/23149111641 (pull_request, failed at `docker build`) ## Additional Notes N/A Signed-off-by: Quang Nguyen --- .github/workflows/images.yaml | 20 ++++++++++++++++++++ .github/workflows/release-images.yaml | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index b1134be36f..8c7fb41682 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -138,6 +138,26 @@ jobs: name: windows-binaries path: output/windows_amd64/ + - name: Ensure Docker daemon is running + shell: pwsh + run: | + $timeout = 120 + $timer = [Diagnostics.Stopwatch]::StartNew() + while ($timer.Elapsed.TotalSeconds -lt $timeout) { + $svc = Get-Service docker -ErrorAction SilentlyContinue + if ($svc -and $svc.Status -ne 'Running') { + Start-Service docker -ErrorAction SilentlyContinue + } + $result = docker info 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Host "Docker daemon is ready" + return + } + Write-Host "Waiting for Docker daemon to start..." + Start-Sleep -Seconds 5 + } + throw "Docker daemon failed to start within $timeout seconds" + - name: Az CLI login uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 if: ${{ github.event_name == 'merge_group' }} diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index ea75a518ae..6e82dd10dd 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -114,6 +114,26 @@ jobs: name: windows-binaries path: output/windows_amd64/ + - name: Ensure Docker daemon is running + shell: pwsh + run: | + $timeout = 120 + $timer = [Diagnostics.Stopwatch]::StartNew() + while ($timer.Elapsed.TotalSeconds -lt $timeout) { + $svc = Get-Service docker -ErrorAction SilentlyContinue + if ($svc -and $svc.Status -ne 'Running') { + Start-Service docker -ErrorAction SilentlyContinue + } + $result = docker info 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Host "Docker daemon is ready" + return + } + Write-Host "Waiting for Docker daemon to start..." + Start-Sleep -Seconds 5 + } + throw "Docker daemon failed to start within $timeout seconds" + - name: Install Cosign uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 From 39f8af1c7416f3ea7241eed6c5153e4c4c5672bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:47:14 -0400 Subject: [PATCH 265/448] deps: bump azure/setup-helm from 4.3.1 to 5.0.0 (#2131) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [azure/setup-helm](https://github.com/azure/setup-helm) from 4.3.1 to 5.0.0.
Release notes

Sourced from azure/setup-helm's releases.

v5.0.0

Changed

Changelog

Sourced from azure/setup-helm's changelog.

Change Log

[5.0.0] - 2026-03-23

Changed

[4.3.1] - 2025-08-12

Changed

Added

[4.3.0] - 2025-02-15

  • #152 feat: log when restoring from cache
  • #157 Dependencies Update
  • #137 Add dependabot

[4.2.0] - 2024-04-15

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azure/setup-helm&package-manager=github_actions&previous-version=4.3.1&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 17a53112f4..4041a2b317 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -24,7 +24,7 @@ jobs: with: fetch-depth: 0 - - uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1 + - uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0 id: install - name: Install Cosign From 89bd87f016168d3a0a2b1ad9f96a46194ece85d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 18:47:01 -0400 Subject: [PATCH 266/448] chore(deps): bump picomatch from 2.3.1 to 2.3.2 in /site in the npm_and_yarn group across 1 directory (#2133) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 1 update in the /site directory: [picomatch](https://github.com/micromatch/picomatch). Updates `picomatch` from 2.3.1 to 2.3.2
Release notes

Sourced from picomatch's releases.

2.3.2

This is a security release fixing several security relevant issues.

What's Changed

Full Changelog: https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2

Changelog

Sourced from picomatch's changelog.

Release history

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

  • Changelogs are for humans, not machines.
  • There should be an entry for every single version.
  • The same types of changes should be grouped.
  • Versions and sections should be linkable.
  • The latest version comes first.
  • The release date of each versions is displayed.
  • Mention whether you follow Semantic Versioning.

Changelog entries are classified using the following labels (from keep-a-changelog):

  • Added for new features.
  • Changed for changes in existing functionality.
  • Deprecated for soon-to-be removed features.
  • Removed for now removed features.
  • Fixed for any bug fixes.
  • Security in case of vulnerabilities.

4.0.0 (2024-02-07)

Fixes

Changed

3.0.1

Fixes

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=picomatch&package-manager=npm_and_yarn&previous-version=2.3.1&new-version=2.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 4594b21ac3..047aa79567 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -170,7 +170,6 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/client-common": "5.48.1", "@algolia/requester-browser-xhr": "5.48.1", @@ -296,7 +295,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2101,7 +2099,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2124,7 +2121,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2234,7 +2230,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2656,7 +2651,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3491,7 +3485,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/babel": "3.9.2", "@docusaurus/bundler": "3.9.2", @@ -3750,7 +3743,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/logger": "3.9.2", @@ -4863,7 +4855,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5163,7 +5154,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5529,7 +5519,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -5874,7 +5863,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5941,7 +5929,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5987,7 +5974,6 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/abtesting": "1.14.1", "@algolia/client-abtesting": "5.48.1", @@ -6597,7 +6583,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7617,7 +7602,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9138,7 +9122,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13767,7 +13750,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14298,9 +14280,10 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -14342,7 +14325,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15216,7 +15198,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -16089,7 +16070,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16102,7 +16082,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -16155,7 +16134,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -16182,7 +16160,6 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17334,7 +17311,6 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, - "peer": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -18275,8 +18251,7 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "peer": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18348,7 +18323,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18704,7 +18678,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18900,7 +18873,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", From 724aedf64172f505e851a2aeabe99579e845a1a6 Mon Sep 17 00:00:00 2001 From: Jeremy Rickards <9338170+rickardsjp@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:54:20 +0100 Subject: [PATCH 267/448] feat(advanced-metrics): Add Support for Topology (Availability) Zone Labels (#1657) # Description This PR introduces availability zone labels ([topology.kubernetes.io/zone](https://kubernetes.io/docs/reference/labels-annotations-taints/#topologykubernetesiozone)) for remote context advanced metrics. With this PR, it is possible to add the `zone` to metrics as sourceLabel or destinationLabel via the MetricsConfiguration CRD. The data is added via the enricher component to the RetinaMetadata in the Flow struct's Extensions attribute, because the node controller already has access to the labels of the Nodes. ## Related Issue https://github.com/microsoft/retina/issues/1654 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ![img](https://github.com/user-attachments/assets/1c871966-821a-4260-b52b-3a84577c0c18) ## Additional Notes We have not added it to the local context because we don't see the value in adding just one zone to a pod. We have not added it to the hubble scenario because hubble doesn't support availability zones for the destination yet. Tagging the co-authors: @ScheererJ @rrhubenov --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Jeremy Rickards --- pkg/common/endpoint.go | 7 ++ pkg/common/node.go | 8 +- pkg/common/types.go | 3 + pkg/controllers/cache/cache_test.go | 8 +- pkg/controllers/daemon/node/controller.go | 2 +- pkg/enricher/enricher.go | 31 ++++++ pkg/enricher/enricher_test.go | 118 ++++++++++++++++++++++ pkg/module/metrics/types.go | 18 ++++ pkg/module/metrics/types_test.go | 38 +++++++ pkg/utils/flow_utils.go | 57 +++++++++-- pkg/utils/utils_linux_test.go | 48 +++++++++ 11 files changed, 323 insertions(+), 15 deletions(-) diff --git a/pkg/common/endpoint.go b/pkg/common/endpoint.go index d6d9c9037f..fee710774f 100644 --- a/pkg/common/endpoint.go +++ b/pkg/common/endpoint.go @@ -29,6 +29,7 @@ func (ep *RetinaEndpoint) DeepCopy() interface{} { newEp := &RetinaEndpoint{ BaseObject: ep.BaseObject.DeepCopy(), + nodeIP: ep.nodeIP, } if ep.ownerRefs != nil { @@ -181,6 +182,12 @@ func (ep *RetinaEndpoint) PrimaryNetIP() (net.IP, error) { return nil, errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, ep.Key()) } +func (ep *RetinaEndpoint) NodeIP() string { + ep.RLock() + defer ep.RUnlock() + return ep.nodeIP +} + func (o *OwnerReference) DeepCopy() *OwnerReference { return &OwnerReference{ Kind: o.Kind, diff --git a/pkg/common/node.go b/pkg/common/node.go index 46735bbdf1..4e00ff9658 100644 --- a/pkg/common/node.go +++ b/pkg/common/node.go @@ -4,16 +4,18 @@ package common import "net" -func NewRetinaNode(name string, ip net.IP) *RetinaNode { +func NewRetinaNode(name string, ip net.IP, zone string) *RetinaNode { return &RetinaNode{ name: name, ip: ip, + zone: zone, } } func (n *RetinaNode) DeepCopy() interface{} { newN := &RetinaNode{ name: n.name, + zone: n.zone, } if n.ip != nil { @@ -31,3 +33,7 @@ func (n *RetinaNode) IPString() string { func (n *RetinaNode) Name() string { return n.name } + +func (n *RetinaNode) Zone() string { + return n.zone +} diff --git a/pkg/common/types.go b/pkg/common/types.go index 5905dc6ce1..359b23bd49 100644 --- a/pkg/common/types.go +++ b/pkg/common/types.go @@ -40,6 +40,7 @@ type RetinaEndpoint struct { containers []*RetinaContainer labels map[string]string annotations map[string]string + nodeIP string } func isIPV4(ipAddress string) bool { @@ -59,6 +60,7 @@ func RetinaEndpointCommonFromAPI(retinaEndpoint *retinav1alpha1.RetinaEndpoint) containers: []*RetinaContainer{}, labels: retinaEndpoint.Labels, annotations: make(map[string]string), + nodeIP: retinaEndpoint.Spec.NodeIP, } for _, ownerRef := range retinaEndpoint.Spec.OwnerReferences { @@ -203,6 +205,7 @@ type OwnerReference struct { type RetinaNode struct { name string ip net.IP + zone string } type APIServerObject struct { diff --git a/pkg/controllers/cache/cache_test.go b/pkg/controllers/cache/cache_test.go index 4ba36eea87..11beee52c6 100644 --- a/pkg/controllers/cache/cache_test.go +++ b/pkg/controllers/cache/cache_test.go @@ -152,7 +152,7 @@ func TestCacheNodes(t *testing.T) { c := New(p) assert.NotNil(t, c) - addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4)) + addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4), "zone-1") var wg sync.WaitGroup wg.Add(2) @@ -221,7 +221,7 @@ func TestAddPodSvcNodeSameIP(t *testing.T) { assert.Equal(t, addSvc.Name(), svc.Name()) assert.Equal(t, addSvc.Namespace(), svc.Namespace()) - addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4)) + addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4), "zone-1") err = c.UpdateRetinaNode(addNode) assert.NoError(t, err) @@ -276,7 +276,7 @@ func TestAddPodSvcNodeSameIPDiffNS(t *testing.T) { assert.Equal(t, addSvc.Name(), svc.Name()) assert.Equal(t, addSvc.Namespace(), svc.Namespace()) - addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4)) + addNode := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4), "zone-1") err = c.UpdateRetinaNode(addNode) assert.NoError(t, err) @@ -358,7 +358,7 @@ func TestFailDelete(t *testing.T) { err = c.DeleteRetinaSvc(svc.Key()) assert.Error(t, err) - node := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4)) + node := common.NewRetinaNode("node1", net.IPv4(1, 2, 3, 4), "zone-1") err = c.DeleteRetinaNode(node.Name()) assert.Error(t, err) diff --git a/pkg/controllers/daemon/node/controller.go b/pkg/controllers/daemon/node/controller.go index cdc48486ea..f085a1dfbb 100644 --- a/pkg/controllers/daemon/node/controller.go +++ b/pkg/controllers/daemon/node/controller.go @@ -80,7 +80,7 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. return ctrl.Result{}, nil } - retinaNodeCommon := retinaCommon.NewRetinaNode(node.Name, net.ParseIP(node.Status.Addresses[0].Address)) + retinaNodeCommon := retinaCommon.NewRetinaNode(node.Name, net.ParseIP(node.Status.Addresses[0].Address), node.Labels[corev1.LabelTopologyZone]) if err := r.cache.UpdateRetinaNode(retinaNodeCommon); err != nil { r.l.Error("Failed to update RetinaNode in Cache", zap.Error(err), zap.String("Node", req.NamespacedName.String())) return ctrl.Result{}, err diff --git a/pkg/enricher/enricher.go b/pkg/enricher/enricher.go index 122d5819a1..408e4dfed2 100644 --- a/pkg/enricher/enricher.go +++ b/pkg/enricher/enricher.go @@ -14,6 +14,7 @@ import ( "github.com/microsoft/retina/pkg/common" "github.com/microsoft/retina/pkg/controllers/cache" "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/utils" "go.uber.org/zap" ) @@ -148,6 +149,17 @@ func (e *Enricher) enrich(ev *v1.Event) { flow.Destination = e.getEndpoint(dstObj) } + // Resolve zones lazily from the node cache using the pod's nodeIP. + srcZone := e.zoneFromObj(srcObj) + dstZone := e.zoneFromObj(dstObj) + + ext := utils.GetExtensionsStruct(flow) + if ext == nil { + ext = utils.NewExtensions() + } + utils.AddZones(ext, srcZone, dstZone) + utils.SetExtensions(flow, ext) + ev.Event = flow e.l.Debug("enriched flow", zap.Any("flow", flow)) e.export(ev) @@ -208,3 +220,22 @@ func (e *Enricher) Write(ev *v1.Event) { func (e *Enricher) ExportReader() *container.RingReader { return container.NewRingReader(e.outputRing, e.outputRing.OldestWrite()) } + +// zoneFromObj resolves the availability zone for a cached object by looking up +// the node from the cache at flow time, avoiding startup race conditions. +func (e *Enricher) zoneFromObj(obj interface{}) string { + if obj == nil { + return "unknown" + } + if o, ok := obj.(*common.RetinaEndpoint); ok { + if nodeIP := o.NodeIP(); nodeIP != "" { + node := e.cache.GetNodeByIP(nodeIP) + if node != nil { + if z := node.Zone(); z != "" { + return z + } + } + } + } + return "unknown" +} diff --git a/pkg/enricher/enricher_test.go b/pkg/enricher/enricher_test.go index f68cbc9965..7f818923fd 100644 --- a/pkg/enricher/enricher_test.go +++ b/pkg/enricher/enricher_test.go @@ -12,14 +12,17 @@ import ( "github.com/cilium/cilium/api/v1/flow" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" + retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" "github.com/microsoft/retina/pkg/common" "github.com/microsoft/retina/pkg/controllers/cache" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/pubsub" + "github.com/microsoft/retina/pkg/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" "google.golang.org/protobuf/types/known/timestamppb" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( @@ -239,3 +242,118 @@ func assertEqualEndpoint(t *testing.T, expected *common.RetinaEndpoint, actual * assert.Equal(t, expected.Namespace(), actual.GetNamespace()) assert.Equal(t, expected.Name(), actual.GetPodName()) } + +func TestEnricherZoneResolution(t *testing.T) { + opts := log.GetDefaultLogOpts() + opts.Level = "debug" + _, err := log.SetupZapLogger(opts) + require.NoError(t, err) + + c := cache.New(pubsub.New()) + + // Add a node with a zone to the cache. + node := common.NewRetinaNode("node-1", net.IPv4(10, 0, 0, 100), "zone-1") + require.NoError(t, c.UpdateRetinaNode(node)) + + // Create endpoints with nodeIP pointing to the node above. + srcEp := common.RetinaEndpointCommonFromAPI(&retinav1alpha1.RetinaEndpoint{ + ObjectMeta: metav1.ObjectMeta{Name: "src-pod", Namespace: "ns1"}, + Spec: retinav1alpha1.RetinaEndpointSpec{ + PodIP: "1.1.1.1", + PodIPs: []string{"1.1.1.1"}, + NodeIP: "10.0.0.100", + }, + }) + dstEp := common.RetinaEndpointCommonFromAPI(&retinav1alpha1.RetinaEndpoint{ + ObjectMeta: metav1.ObjectMeta{Name: "dst-pod", Namespace: "ns2"}, + Spec: retinav1alpha1.RetinaEndpointSpec{ + PodIP: "2.2.2.2", + PodIPs: []string{"2.2.2.2"}, + NodeIP: "10.0.0.100", + }, + }) + + require.NoError(t, c.UpdateRetinaEndpoint(srcEp)) + require.NoError(t, c.UpdateRetinaEndpoint(dstEp)) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + e := newEnricher(ctx, c) + + // Get the export reader before running and writing, so we don't miss events. + oreader := e.ExportReader() + e.Run() + + // Write multiple events to ensure at least one makes it through the ring. + for range 3 { + e.Write(&v1.Event{ + Timestamp: timestamppb.Now(), + Event: &flow.Flow{ + IP: &flow.IP{ + IpVersion: 1, + Source: "1.1.1.1", + Destination: "2.2.2.2", + }, + }, + }) + time.Sleep(100 * time.Millisecond) + } + + enrichedEv := oreader.NextFollow(ctx) + require.NotNil(t, enrichedEv) + + enrichedFlow := enrichedEv.Event.(*flow.Flow) + assert.Equal(t, "zone-1", utils.SourceZone(enrichedFlow)) + assert.Equal(t, "zone-1", utils.DestinationZone(enrichedFlow)) +} + +func TestEnricherZoneResolution_NoNode(t *testing.T) { + opts := log.GetDefaultLogOpts() + opts.Level = "debug" + _, err := log.SetupZapLogger(opts) + require.NoError(t, err) + + c := cache.New(pubsub.New()) + + // Create endpoint with nodeIP but no node in cache. + ep := common.RetinaEndpointCommonFromAPI(&retinav1alpha1.RetinaEndpoint{ + ObjectMeta: metav1.ObjectMeta{Name: "pod1", Namespace: "ns1"}, + Spec: retinav1alpha1.RetinaEndpointSpec{ + PodIP: "3.3.3.3", + PodIPs: []string{"3.3.3.3"}, + NodeIP: "10.0.0.200", + }, + }) + require.NoError(t, c.UpdateRetinaEndpoint(ep)) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + e := newEnricher(ctx, c) + + oreader := e.ExportReader() + e.Run() + + for range 3 { + e.Write(&v1.Event{ + Timestamp: timestamppb.Now(), + Event: &flow.Flow{ + IP: &flow.IP{ + IpVersion: 1, + Source: "3.3.3.3", + Destination: "9.9.9.9", + }, + }, + }) + time.Sleep(100 * time.Millisecond) + } + + enrichedEv := oreader.NextFollow(ctx) + require.NotNil(t, enrichedEv) + + enrichedFlow := enrichedEv.Event.(*flow.Flow) + // Node not in cache, so zone should be "unknown". + assert.Equal(t, "unknown", utils.SourceZone(enrichedFlow)) + assert.Equal(t, "unknown", utils.DestinationZone(enrichedFlow)) +} diff --git a/pkg/module/metrics/types.go b/pkg/module/metrics/types.go index 41d923a661..5887c1ab5d 100644 --- a/pkg/module/metrics/types.go +++ b/pkg/module/metrics/types.go @@ -44,6 +44,9 @@ const ( // workload context option workloadCtxOption = "workload" + // zone context option + zoneCtxOption = "zone" + // localContext means only the pods on this node will be watched // and only these events will be enriched localContext enrichmentContext = "local" @@ -95,6 +98,7 @@ type ContextOptions struct { Workload bool Service bool Port bool + Zone bool } type DirtyCachePod struct { @@ -129,6 +133,8 @@ func NewCtxOption(opts []string, option ctxOptionType) *ContextOptions { c.Service = true case portCtxOption: c.Port = true + case zoneCtxOption: + c.Zone = true } } @@ -170,6 +176,10 @@ func (c *ContextOptions) getLabels() []string { labels = append(labels, prefix+portCtxOption) } + if c.Zone { + labels = append(labels, prefix+zoneCtxOption) + } + return labels } @@ -310,6 +320,14 @@ func (c *ContextOptions) getByDirectionValues(f *flow.Flow, dest bool) []string } } + if c.Zone { + if !dest { + values = append(values, utils.SourceZone(f)) + } else { + values = append(values, utils.DestinationZone(f)) + } + } + return values } diff --git a/pkg/module/metrics/types_test.go b/pkg/module/metrics/types_test.go index d488bbd358..1d901e3d40 100644 --- a/pkg/module/metrics/types_test.go +++ b/pkg/module/metrics/types_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/cilium/cilium/api/v1/flow" + "github.com/microsoft/retina/pkg/utils" "github.com/stretchr/testify/assert" ) @@ -130,6 +131,34 @@ func TestNewCtxOps(t *testing.T) { }, expectedVals: []string{"", "unknown", "unknown"}, }, + { + name: "source zone option", + opts: []string{"namespace", "zone"}, + ctxType: source, + expected: []string{ + "source_namespace", "source_zone", + }, + f: flowWithZones("zone-1", "zone-2"), + expectedVals: []string{"unknown", "zone-1"}, + }, + { + name: "destination zone option", + opts: []string{"namespace", "zone"}, + ctxType: destination, + expected: []string{ + "destination_namespace", "destination_zone", + }, + f: flowWithZones("zone-1", "zone-2"), + expectedVals: []string{"unknown", "zone-2"}, + }, + { + name: "zone with no extensions", + opts: []string{"zone"}, + ctxType: source, + expected: []string{"source_zone"}, + f: &flow.Flow{}, + expectedVals: []string{"unknown"}, + }, } for _, tc := range tt { @@ -139,3 +168,12 @@ func TestNewCtxOps(t *testing.T) { assert.Equal(t, tc.expectedVals, values, "values should match %s", tc.name) } } + +// flowWithZones creates a flow with zone extensions populated. +func flowWithZones(srcZone, dstZone string) *flow.Flow { + f := &flow.Flow{} + ext := utils.NewExtensions() + utils.AddZones(ext, srcZone, dstZone) + utils.SetExtensions(f, ext) + return f +} diff --git a/pkg/utils/flow_utils.go b/pkg/utils/flow_utils.go index 0313d36ca2..4a41b32d99 100644 --- a/pkg/utils/flow_utils.go +++ b/pkg/utils/flow_utils.go @@ -33,6 +33,10 @@ const ( ExtKeyPrevObservedPackets = "previously_observed_packets" ExtKeyPrevObservedBytes = "previously_observed_bytes" ExtKeyPrevObservedTCPFlags = "previously_observed_tcp_flags" + ExtKeySourceZone = "source_zone" + ExtKeyDestinationZone = "destination_zone" + + zoneUnknown = "unknown" ) // ToFlow returns a flow.Flow object. @@ -152,9 +156,9 @@ func SetExtensions(f *flow.Flow, s *structpb.Struct) { f.Extensions = ext } -// getExtensionsStruct extracts the structpb.Struct from flow.Extensions. +// GetExtensionsStruct extracts the structpb.Struct from flow.Extensions. // Returns nil if Extensions is nil or not a Struct. -func getExtensionsStruct(f *flow.Flow) *structpb.Struct { +func GetExtensionsStruct(f *flow.Flow) *structpb.Struct { if f == nil || f.GetExtensions() == nil { return nil } @@ -207,7 +211,7 @@ func AddPreviouslyObservedTCPFlags(s *structpb.Struct, syn, ack, fin, rst, psh, } func PreviouslyObservedTCPFlags(f *flow.Flow) map[string]uint32 { - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return nil } @@ -231,7 +235,7 @@ func AddPreviouslyObservedBytes(s *structpb.Struct, bytes uint32) { } func PreviouslyObservedBytes(f *flow.Flow) uint32 { - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return 0 } @@ -251,7 +255,7 @@ func AddPreviouslyObservedPackets(s *structpb.Struct, packets uint32) { } func PreviouslyObservedPackets(f *flow.Flow) uint32 { - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return 0 } @@ -291,7 +295,7 @@ func GetTCPID(f *flow.Flow) uint64 { if f.GetL4() == nil || f.GetL4().GetTCP() == nil { return 0 } - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return 0 } @@ -345,7 +349,7 @@ func GetDNS(f *flow.Flow) (*flow.DNS, DNSType, uint32) { return nil, DNSType_UNKNOWN, 0 } dns := f.L7.GetDns() - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return dns, DNSType_UNKNOWN, 0 } @@ -400,7 +404,7 @@ func AddPacketSize(s *structpb.Struct, packetSize uint32) { } func PacketSize(f *flow.Flow) uint32 { - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return 0 } @@ -438,7 +442,7 @@ func DropReasonDescription(f *flow.Flow) string { if f == nil { return "" } - s := getExtensionsStruct(f) + s := GetExtensionsStruct(f) if s == nil { return "" } @@ -460,3 +464,38 @@ func decodeTime(nanoseconds int64) (pbTime *timestamppb.Timestamp, err error) { } return pbTime, nil } + +// AddZones adds source and destination availability zones to the flow's extensions. +func AddZones(s *structpb.Struct, srcZone, dstZone string) { + if s == nil { + return + } + s.Fields[ExtKeySourceZone] = structpb.NewStringValue(srcZone) + s.Fields[ExtKeyDestinationZone] = structpb.NewStringValue(dstZone) +} + +// SourceZone returns the source availability zone from the flow's extensions. +func SourceZone(f *flow.Flow) string { + s := GetExtensionsStruct(f) + if s == nil { + return zoneUnknown + } + v, ok := s.GetFields()[ExtKeySourceZone] + if !ok { + return zoneUnknown + } + return v.GetStringValue() +} + +// DestinationZone returns the destination availability zone from the flow's extensions. +func DestinationZone(f *flow.Flow) string { + s := GetExtensionsStruct(f) + if s == nil { + return zoneUnknown + } + v, ok := s.GetFields()[ExtKeyDestinationZone] + if !ok { + return zoneUnknown + } + return v.GetStringValue() +} diff --git a/pkg/utils/utils_linux_test.go b/pkg/utils/utils_linux_test.go index 9d5767ac1f..a142ddf102 100644 --- a/pkg/utils/utils_linux_test.go +++ b/pkg/utils/utils_linux_test.go @@ -167,6 +167,54 @@ func TestAddDropReason(t *testing.T) { } } +func TestZoneHelpers(t *testing.T) { + tests := []struct { + name string + srcZone string + dstZone string + expectedSrcZone string + expectedDstZone string + }{ + { + name: "both zones set", + srcZone: "zone-1", + dstZone: "zone-2", + expectedSrcZone: "zone-1", + expectedDstZone: "zone-2", + }, + { + name: "empty zones stored as empty strings", + srcZone: "", + dstZone: "", + expectedSrcZone: "", + expectedDstZone: "", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + f := &flow.Flow{} + ext := NewExtensions() + AddZones(ext, tc.srcZone, tc.dstZone) + SetExtensions(f, ext) + + assert.Equal(t, tc.expectedSrcZone, SourceZone(f)) + assert.Equal(t, tc.expectedDstZone, DestinationZone(f)) + }) + } +} + +func TestZoneHelpers_NilExtensions(t *testing.T) { + f := &flow.Flow{} + assert.Equal(t, "unknown", SourceZone(f)) + assert.Equal(t, "unknown", DestinationZone(f)) +} + +func TestAddZones_NilStruct(t *testing.T) { + // Should not panic. + AddZones(nil, "zone-1", "zone-2") +} + func TestIsDefaultRoute(t *testing.T) { tests := []struct { Route netlink.Route From d900d152bd91f8f48aba5e9bf241e6d43ff88e0d Mon Sep 17 00:00:00 2001 From: Felix Nuworsu <130885230+Fnuworsu@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:52:21 -0500 Subject: [PATCH 268/448] fix: set capture start time in reconciler for CRD-created captures (#2134) ## Description Fixes #2108 When a Capture is created via CRD/YAML (not CLI), the `Status.StartTime` is never set. This causes the capture job to fail with: ``` failed to parse capture start timestamp: failed to create timestamp from string: parsing time "" as "20060102150405UTC": cannot parse "" as "2006" ``` ### Root Cause The CLI path sets `capture.Status.StartTime = file.Now()` in `createCaptureF()`. However, the operator reconciler's `handleUpdate()` method does not initialize `StartTime` before calling `createJobsFromCapture()`. Since `StartTime` is nil, `GetPodAnnotationsFromCapture()` omits the timestamp annotation, which causes `renderJob()` to fail when parsing the resulting empty string. ### Fix This PR ensures that `capture.Status.StartTime` is set to `metav1.Now()` within `handleUpdate()` for CRD-created captures, mirroring the CLI's behavior. The updated status is properly persisted via `updateStatus()`. ### Changes - `pkg/controllers/operator/capture/controller.go`: Added logic to correctly initialize `StartTime` in `handleUpdate()` if it hasn't been set yet. ### Verification (Local Testing) **Before the fix (reproducing the issue):** ``` === RUN TestHandleUpdateSetsStartTime ts=2026-03-26T01:55:50.816-0500 level=info caller=utils/capture_image.go:57 msg="Using capture workload image ghcr.io/microsoft/retina/retina-agent:v0.0.1 with version determined by test" ts=2026-03-26T01:55:50.816-0500 level=error caller=capture/crd_to_job.go:110 msg="Failed to get apiserver URL" error="invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable" errorCauses= errorError="unsupported value type" ts=2026-03-26T01:55:50.817-0500 level=error caller=capture/controller.go:229 msg="Failed to translate Capture to jobs" error="At least one output configuration should be set" Capture=default/test-capture ts=2026-03-26T01:55:50.817-0500 level=error caller=capture/controller.go:240 msg="Failed to translate Capture to jobs" error="At least one output configuration should be set" Capture=default/test-capture controller_unit_test.go:99: expected StartTime to be set after handleUpdate, but it was nil. handleUpdate error: --- FAIL: TestHandleUpdateSetsStartTime (0.00s) FAIL ``` **After the fix:** ``` === RUN TestHandleUpdateSetsStartTime ts=2026-03-26T01:57:01.346-0500 level=info caller=utils/capture_image.go:57 msg="Using capture workload image ghcr.io/microsoft/retina/retina-agent:v0.0.1 with version determined by test" ts=2026-03-26T01:57:01.346-0500 level=error caller=capture/crd_to_job.go:110 msg="Failed to get apiserver URL" error="invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable" errorCauses= errorError="unsupported value type" ts=2026-03-26T01:57:01.348-0500 level=error caller=capture/controller.go:229 msg="Failed to translate Capture to jobs" error="At least one output configuration should be set" Capture=default/test-capture ts=2026-03-26T01:57:01.348-0500 level=error caller=capture/controller.go:240 msg="Failed to translate Capture to jobs" error="At least one output configuration should be set" Capture=default/test-capture controller_unit_test.go:102: StartTime was correctly set to: 2026-03-26 01:57:01 -0500 CDT --- PASS: TestHandleUpdateSetsStartTime (0.00s) PASS ``` Signed-off-by: Fnuworsu Signed-off-by: Felix Nuworsu --- pkg/controllers/operator/capture/controller.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/controllers/operator/capture/controller.go b/pkg/controllers/operator/capture/controller.go index 3c86f44784..121213d884 100644 --- a/pkg/controllers/operator/capture/controller.go +++ b/pkg/controllers/operator/capture/controller.go @@ -307,6 +307,16 @@ func (cr *CaptureReconciler) handleUpdate(ctx context.Context, capture *retinav1 return cr.updateCaptureStatusFromJobs(ctx, capture, captureJobList.Items) } + // Set StartTime for CRD-created captures since the operator doesn't do it by default + // (unlike the CLI), and missing it causes a timestamp parsing error in the capture job. + if capture.Status.StartTime == nil { + now := metav1.Now() + capture.Status.StartTime = &now + if _, err := cr.updateStatus(ctx, capture); err != nil { + return ctrl.Result{}, err + } + } + // create SAS URL and then secret for the Capture if managed storage account is enabled. // Don't repeat the process if the secret already exists. if cr.managedStorageAccountEnabled() { From 5fbb9b5bcdd9af087525027d6e3ffc204c0899e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 19:00:30 -0400 Subject: [PATCH 269/448] deps: bump actions/deploy-pages from 4.0.5 to 5.0.0 (#2137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 4.0.5 to 5.0.0.
Release notes

Sourced from actions/deploy-pages's releases.

v5.0.0

Changelog


See details of all code changes since previous release.

:warning: For use with products other than GitHub.com, such as GitHub Enterprise Server, please consult the compatibility table.

Commits
  • cd2ce8f Merge pull request #404 from salmanmkc/node24
  • bbe2a95 Update Node.js version to 24.x
  • 854d7aa Merge pull request #374 from actions/Jcambass-patch-1
  • 306bb81 Add workflow file for publishing releases to immutable action package
  • b742728 Merge pull request #360 from actions/dependabot/npm_and_yarn/npm_and_yarn-513...
  • 7273294 Bump braces in the npm_and_yarn group across 1 directory
  • 963791f Merge pull request #361 from actions/dependabot-friendly
  • 51bb29d Make the rebuild dist workflow safer for Dependabot
  • 89f3d10 Merge pull request #358 from actions/dependabot/npm_and_yarn/non-breaking-cha...
  • bce7355 Merge branch 'main' into dependabot/npm_and_yarn/non-breaking-changes-99c12deb21
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/deploy-pages&package-manager=github_actions&previous-version=4.0.5&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index ff1100b6aa..0b8841336d 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -53,4 +53,4 @@ jobs: uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 From dd9185bd6de9f62624013865d18421ae076e0dd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:38:40 -0400 Subject: [PATCH 270/448] deps: bump actions/configure-pages from 5.0.0 to 6.0.0 (#2136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 5.0.0 to 6.0.0.
Release notes

Sourced from actions/configure-pages's releases.

v6.0.0

Changelog

See details of all code changes since previous release.

Commits
  • 45bfe01 Merge pull request #186 from salmanmkc/node24
  • d8770c2 Update Node version from 20 to 24 in action.yml
  • cb8a1a3 upgrade to node 24
  • d560657 Merge pull request #165 from actions/Jcambass-patch-1
  • 35e0ac4 Upgrade IA Publish
  • 1dfbcbf Merge pull request #163 from actions/Jcambass-patch-1
  • 2f4f988 Add workflow file for publishing releases to immutable action package
  • 0d7570c Merge pull request #162 from actions/pin-draft-release-verssion
  • 3ea1966 pin draft release version
  • aabcbc4 Merge pull request #160 from actions/dependabot/npm_and_yarn/espree-10.1.0
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 0b8841336d..f050d5e00d 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -50,7 +50,7 @@ jobs: timeout-minutes: 10 steps: - name: Setup Pages - uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 + uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 From 0db4013b9046c999987552d45af4e62ddbda2f23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 23:52:50 -0400 Subject: [PATCH 271/448] deps: bump sigstore/cosign-installer from 4.1.0 to 4.1.1 (#2135) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.1.0 to 4.1.1.
Release notes

Sourced from sigstore/cosign-installer's releases.

v4.1.1

What's Changed

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 4041a2b317..4d45eaa467 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -28,7 +28,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 6e82dd10dd..bb048eab86 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -38,7 +38,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -135,7 +135,7 @@ jobs: throw "Docker daemon failed to start within $timeout seconds" - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -188,7 +188,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -236,7 +236,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -282,7 +282,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -328,7 +328,7 @@ jobs: uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Install Cosign - uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0 + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From 92ac21cab049ec73123765601d3cccec4b57e98e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 01:38:16 -0400 Subject: [PATCH 272/448] chore(deps): bump node-forge from 1.3.2 to 1.4.0 in /site in the npm_and_yarn group across 1 directory (#2139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 1 update in the /site directory: [node-forge](https://github.com/digitalbazaar/forge). Updates `node-forge` from 1.3.2 to 1.4.0
Changelog

Sourced from node-forge's changelog.

1.4.0 - 2026-03-24

Security

  • HIGH: Denial of Service in BigInteger.modInverse()
    • A Denial of Service (DoS) vulnerability exists due to an infinite loop in the BigInteger.modInverse() function (inherited from the bundled jsbn library). When modInverse() is called with a zero value as input, the internal Extended Euclidean Algorithm enters an unreachable exit condition, causing the process to hang indefinitely and consume 100% CPU.
    • Reported by Kr0emer.
    • CVE ID: CVE-2026-33891
    • GHSA ID: GHSA-5gfm-wpxj-wjgq
  • HIGH: Signature forgery in RSA-PKCS due to ASN.1 extra field.
    • RSASSA PKCS#1 v1.5 signature verification accepts forged signatures for low public exponent keys (e=3). Attackers can forge signatures by stuffing "garbage" bytes within the ASN.1 structure in order to construct a signature that passes verification, enabling Bleichenbacher style forgery. This issue is similar to CVE-2022-24771, but adds bytes in an addition field within the ASN.1 structure, rather than outside of it.
    • Additionally, forge does not validate that signatures include a minimum of 8 bytes of padding as defined by the specification, providing attackers additional space to construct Bleichenbacher forgeries.
    • Reported as part of a U.C. Berkeley security research project by:
      • Austin Chu, Sohee Kim, and Corban Villa.
    • CVE ID: CVE-2026-33894
    • GHSA ID: GHSA-ppp5-5v6c-4jwp
  • HIGH: Signature forgery in Ed25519 due to missing S < L check.
    • Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (S >= L). A valid signature and its S + L variant both verify in forge, while Node.js crypto.verify (OpenSSL-backed) rejects the S + L variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed.
    • Reported as part of a U.C. Berkeley security research project by:
      • Austin Chu, Sohee Kim, and Corban Villa.
    • CVE ID: CVE-2026-33895
    • GHSA ID: GHSA-q67f-28xg-22rw
  • HIGH: basicConstraints bypass in certificate chain verification.
    • pki.verifyCertificateChain() does not enforce RFC 5280 basicConstraints requirements when an intermediate certificate lacks both the basicConstraints and keyUsage extensions. This allows any leaf certificate (without these extensions) to act as a CA and sign other certificates, which node-forge will accept as valid.
    • Reported by Doruk Tan Ozturk (@​peaktwilight) - doruk.ch
    • CVE ID: CVE-2026-33896
    • GHSA ID: GHSA-2328-f5f3-gj25

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=node-forge&package-manager=npm_and_yarn&previous-version=1.3.2&new-version=1.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 047aa79567..283897ecff 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -13654,9 +13654,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" From a0b7220f1a5b3adde4e3fc81e8f803497b53227a Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 27 Mar 2026 11:45:52 -0400 Subject: [PATCH 273/448] chore(ci): add path filters and PR/merge_group triggers to kapinger workflow (#2110) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The kapinger workflow runs on every push to main regardless of whether kapinger files changed, and has no `pull_request` or `merge_group` triggers so changes aren't validated before merge. Add `paths` filters scoped to `hack/tools/kapinger/**` and the workflow file itself, `pull_request` and `merge_group` triggers, `tags` trigger for releases, and explicit `permissions` block. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI-only change — no manual testing needed. ## Additional Notes Split out from #2096 per review feedback. Signed-off-by: Quang Nguyen --- .github/workflows/kapinger.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index e6482e893d..159872ff8c 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -4,6 +4,19 @@ on: push: branches: - main + paths: + - "hack/tools/kapinger/**" + - ".github/workflows/kapinger.yaml" + tags: + - "v*" + pull_request: + branches: + - main + paths: + - "hack/tools/kapinger/**" + - ".github/workflows/kapinger.yaml" + merge_group: + types: [checks_requested] permissions: contents: read From 10bc9908c23e2061ed3cf75add640d7f6bf0299f Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 27 Mar 2026 11:46:25 -0400 Subject: [PATCH 274/448] fix(e2e): switch VM SKUs to DDSv4 for better quota headroom in eastus2 (#2138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description E2E tests use DSv6/DSv4 family SKUs for node pools, which have limited quota in eastus2. The DDSv4 family has significantly more quota headroom in the same region. This switches both Linux and Windows SKUs to `Standard_D4ds_v4`: - **Linux amd64**: `Standard_D4s_v6` → `Standard_D4ds_v4` - **Windows**: `Standard_D4s_v4` → `Standard_D4ds_v4` - **Scale test**: `Standard_D4s_v6` → `Standard_D4ds_v4` ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Verified `Standard_D4ds_v4` supports Hyper-V Gen V1/V2 and is available in all zones in eastus2 with no restrictions. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- test/e2e/framework/azure/create-cluster.go | 4 ++-- test/e2e/jobs/scale.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/framework/azure/create-cluster.go b/test/e2e/framework/azure/create-cluster.go index 3709b2145e..f390b37738 100644 --- a/test/e2e/framework/azure/create-cluster.go +++ b/test/e2e/framework/azure/create-cluster.go @@ -14,8 +14,8 @@ import ( const ( MaxNumberOfNodes = 3 MaxPodsPerNode = 250 - AgentSKU = "Standard_D4s_v6" - AgentWindowsSKU = "Standard_D4s_v4" + AgentSKU = "Standard_D4ds_v4" + AgentWindowsSKU = "Standard_D4ds_v4" ) var defaultClusterCreateTimeout = 30 * time.Minute diff --git a/test/e2e/jobs/scale.go b/test/e2e/jobs/scale.go index 0b27feb4a3..31b18a3ad5 100644 --- a/test/e2e/jobs/scale.go +++ b/test/e2e/jobs/scale.go @@ -62,7 +62,7 @@ func GetScaleTestInfra(subID, rg, clusterName, location, kubeConfigFilePath stri Nodes: nodes, }). SetPodCidr("100.64.0.0/10"). - SetVMSize("Standard_D4s_v6"). + SetVMSize("Standard_D4ds_v4"). SetNetworkPluginMode("overlay"), nil) job.AddStep(&azure.GetAKSKubeConfig{ From 12cd764ba3cf364ce9de2dc86c4d225831f76cbd Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 27 Mar 2026 11:46:37 -0400 Subject: [PATCH 275/448] chore(ci): build golangci-lint from go.sum to align with project version (#2111) ## Description Currently the golangci-lint workflow uses `golangci-lint-action` with `version: latest`, which drifts from the version pinned in `go.sum`. This causes lint results in CI that don't reproduce locally via `make lint` (#2027). This PR replaces the action with a `go build` step that builds golangci-lint from the version tracked in `go.sum`, so CI uses the exact same version as local `make lint`. It also switches from the action's `only-new-issues` flag to `--new-from-rev` for incremental linting. ## Related Issue Fixes #2027 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. Signed-off-by: Quang Nguyen --- .github/workflows/golangci-lint.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index e5390ae721..db8c28535d 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -34,10 +34,8 @@ jobs: - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version-file: go.mod + - name: Build golangci-lint + run: GOOS=linux GOARCH=amd64 go build -o "$RUNNER_TEMP/golangci-lint" github.com/golangci/golangci-lint/cmd/golangci-lint - name: golangci-lint - uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 - with: - version: latest - args: --concurrency 4 --verbose --config=.golangci.yaml --timeout=25m - only-new-issues: true - skip-cache: true + run: | + "$RUNNER_TEMP/golangci-lint" run --new-from-rev=${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before || 'HEAD~1' }} --concurrency 4 --verbose --config=.golangci.yaml --timeout=25m From 55095d14f7534a34e6054106ac7448757c345ad2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 19:21:23 -0400 Subject: [PATCH 276/448] chore(deps): bump brace-expansion from 1.1.12 to 1.1.13 in /site in the npm_and_yarn group across 1 directory (#2141) Bumps the npm_and_yarn group with 1 update in the /site directory: [brace-expansion](https://github.com/juliangruber/brace-expansion). Updates `brace-expansion` from 1.1.12 to 1.1.13
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=brace-expansion&package-manager=npm_and_yarn&previous-version=1.1.12&new-version=1.1.13)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 283897ecff..c1da7f2467 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -6544,9 +6544,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", From b545d82d68445584eae809633ddb8253eaa8c385 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 00:13:46 +0000 Subject: [PATCH 277/448] deps: bump github/codeql-action from 4.34.1 to 4.35.0 (#2140) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.34.1 to 4.35.0.
Release notes

Sourced from github/codeql-action's releases.

v4.35.0

Commits
  • b8bb9f2 Merge pull request #3776 from github/update-v4.35.0-0078ad667
  • e9cf68b Update changelog for v4.35.0
  • 0078ad6 Merge pull request #3773 from github/update-bundle/codeql-bundle-v2.25.1
  • fa7a15b Add changelog note
  • 8c29faa Update default bundle to codeql-bundle-v2.25.1
  • f94817b Merge pull request #3772 from github/dependabot/npm_and_yarn/yaml-2.8.3
  • dd06097 Bump yaml from 2.8.2 to 2.8.3
  • 5cc552f Merge pull request #3768 from github/dependabot/npm_and_yarn/npm-minor-3536e7...
  • 6b1a9f2 Merge branch 'main' into dependabot/npm_and_yarn/npm-minor-3536e7c6f0
  • 9d3ec57 Merge pull request #3770 from github/dependabot/github_actions/dot-github/wor...
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.34.1&new-version=4.35.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 6263c5c417..f02f140c60 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 5ec05e02e9..f2b5add2bd 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: sarif_file: "trivy-results.sarif" From 841310d0a5fde2d04892ba5e853ba0aece305a7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 00:28:34 +0000 Subject: [PATCH 278/448] chore(deps): bump path-to-regexp from 0.1.12 to 0.1.13 in /site in the npm_and_yarn group across 1 directory (#2147) Bumps the npm_and_yarn group with 1 update in the /site directory: [path-to-regexp](https://github.com/pillarjs/path-to-regexp). Updates `path-to-regexp` from 0.1.12 to 0.1.13
Release notes

Sourced from path-to-regexp's releases.

0.1.13

Important

Full Changelog: https://github.com/pillarjs/path-to-regexp/compare/v0.1.12...v.0.1.13

Changelog

Sourced from path-to-regexp's changelog.

0.1.13 / 2026-03-26

0.1.7 / 2015-07-28

  • Fixed regression with escaped round brackets and matching groups.

0.1.6 / 2015-06-19

  • Replace index feature by outputting all parameters, unnamed and named.

0.1.5 / 2015-05-08

  • Add an index property for position in match result.

0.1.4 / 2015-03-05

  • Add license information

0.1.3 / 2014-07-06

  • Better array support
  • Improved support for trailing slash in non-ending mode

0.1.0 / 2014-03-06

  • add options.end

0.0.2 / 2013-02-10

  • Update to match current express
  • add .license property to component.json
Commits
Maintainer changes

This version was pushed to npm by ulisesgascon, a new releaser for path-to-regexp since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=path-to-regexp&package-manager=npm_and_yarn&previous-version=0.1.12&new-version=0.1.13)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index c1da7f2467..dd1bb88529 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -8947,9 +8947,9 @@ "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/express/node_modules/range-parser": { From adc5bbe3722ac9f1d515bcecdea18f8855fc7258 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 30 Mar 2026 14:40:12 -0400 Subject: [PATCH 279/448] fix(e2e): use available ARM VM SKU for CI (#2150) # Description `Standard_D4pls_v6` is not available in the CI subscription's `eastus2` region, causing e2e cluster creation to fail with `VMSizeNotSupportedForEdgeZone`. Switch to `Standard_D4pds_v5` (Ampere Altra, 4 vCPUs, v5 series) which is available. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Testing Completed Verified `Standard_D4pds_v5` is available in eastus2 via the CI subscription's VM SKU list. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- test/e2e/framework/azure/create-cluster-with-npm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index 76b94348e0..bcd11c59c1 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -21,7 +21,7 @@ const ( clusterTimeout = 15 * time.Minute clusterCreateTicker = 30 * time.Second pollFrequency = 5 * time.Second - AgentARMSKU = "Standard_D4pls_v6" + AgentARMSKU = "Standard_D4pds_v5" AuxilaryNodeCount = 1 AuxilaryARMNodeCount = 2 ) From e2055aefd4a77f1cc00de0dd97590461f372787b Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 30 Mar 2026 17:34:15 -0400 Subject: [PATCH 280/448] fix(test): catch silent CI failures and fix Go 1.26 vet errors (#2145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fixes three classes of pre-existing test/CI issues on main, all discovered during the Cilium v1.19 upgrade (#1788). ### 1. test-summary silently ignores package build failures When `go test -json` reports a package that fails to compile, it emits a `"fail"` event with an empty `Test` field. `test/utsummary/main.go` explicitly skipped counting these, so broken packages produced `failed 0` and exit 0. **Fix**: Count package-level `"fail"` events as build failures when no test-level events exist for that package (to avoid double-counting normal test failures). Also wrap the `go test | test-summary` pipe in `bash -o pipefail` as a second safety net. ### 2. `pkg/common` broken test from #1657 PR #1657 added a `nodeIP` field to `RetinaEndpoint` and populates it from `Spec.NodeIP`, but did not update test expectations in `TestRetinaEndpointCommonFromAPI`. This went undetected due to issue 1 above. **Fix**: Add `nodeIP: hostIP` to both test case expectations. ### 3. Go 1.26 `go vet` failures - **`dropreason_linux_test.go`**: `t.Fatalf` called from non-test goroutine (lines 185, 247); `WaitGroup.Add` called inside goroutine (line 302) - **`common/endpoint.go`**: Non-constant format string passed to `errors.Wrapf` (lines 168, 182) - **`packetparser/mocks`**: Mock references unexported `perfRecord` type from subpackage — regenerating the mock after `go generate` causes a build failure **Fix**: Use error channels instead of `t.Fatalf` in goroutines; move `wg.Add` before goroutine launch; use `"%s"` format specifier; exclude `perfReader` from mockgen (uses unexported return type) and replace with a hand-rolled mock in the test file. ## Related Issue N/A — discovered during the Cilium v1.19 upgrade (#1788). ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ### CI validation of test-summary fix Intentionally pushed without the test fix to confirm CI catches build failures. [Run 23671852095](https://github.com/microsoft/retina/actions/runs/23671852095) correctly failed: ``` Failures (reporting up to 10): github.com/microsoft/retina/pkg/common [build failed] github.com/microsoft/retina/pkg/plugin/dropreason [build failed] github.com/microsoft/retina/pkg/plugin/dropreason/mocks [build failed] github.com/microsoft/retina/pkg/plugin/packetparser [build failed] github.com/microsoft/retina/pkg/plugin/packetparser/mocks [build failed] ran 814; passed 798; failed 5; skipped 11 ``` Previously all passed silently with `failed 0`. ### Local verification ``` $ go vet ./pkg/common/... ./pkg/plugin/dropreason/... ./pkg/plugin/packetparser/... # (no output — clean) $ go test -tags=unit,dashboard ./pkg/common/ ./pkg/plugin/dropreason/ ./pkg/plugin/packetparser/ ok github.com/microsoft/retina/pkg/common 0.005s ok github.com/microsoft/retina/pkg/plugin/dropreason 14.439s ok github.com/microsoft/retina/pkg/plugin/packetparser 3.786s ``` ## Additional Notes N/A --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Quang Nguyen --- Makefile | 2 +- pkg/common/endpoint.go | 4 +- pkg/common/types_test.go | 2 + .../dropreason/dropreason_linux_test.go | 18 ++-- .../dropreason/mocks/mock_types_linux.go | 3 - pkg/plugin/dropreason/types_linux.go | 2 +- .../packetparser/mocks/mock_types_linux.go | 55 +----------- .../packetparser/packetparser_linux_test.go | 84 ++++++++++++------- pkg/plugin/packetparser/types_linux.go | 2 +- test/utsummary/main.go | 23 ++++- 10 files changed, 91 insertions(+), 104 deletions(-) diff --git a/Makefile b/Makefile index 4cfccff752..d335e21dff 100644 --- a/Makefile +++ b/Makefile @@ -457,7 +457,7 @@ COVER_PKG ?= . .PHONY: test test: # Run unit tests. go build -o test-summary ./test/utsummary/main.go - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use -p path)" go test -tags=unit,dashboard -skip=TestE2E* -coverprofile=coverage.out -v -json ./... | ./test-summary --progress --verbose + bash -o pipefail -c 'KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use -p path)" go test -tags=unit,dashboard -skip=TestE2E* -coverprofile=coverage.out -v -json ./... | ./test-summary --progress --verbose' coverage: # Code coverage. # go generate ./... && go test -tags=unit -coverprofile=coverage.out.tmp ./... diff --git a/pkg/common/endpoint.go b/pkg/common/endpoint.go index fee710774f..d4f775b1f1 100644 --- a/pkg/common/endpoint.go +++ b/pkg/common/endpoint.go @@ -165,7 +165,7 @@ func (ep *RetinaEndpoint) PrimaryIP() (string, error) { } } - return "", errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, ep.Key()) + return "", errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, "%s", ep.Key()) } func (ep *RetinaEndpoint) PrimaryNetIP() (net.IP, error) { @@ -179,7 +179,7 @@ func (ep *RetinaEndpoint) PrimaryNetIP() (net.IP, error) { } } - return nil, errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, ep.Key()) + return nil, errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, "%s", ep.Key()) } func (ep *RetinaEndpoint) NodeIP() string { diff --git a/pkg/common/types_test.go b/pkg/common/types_test.go index 5eb0574dc7..d14f9dde4a 100644 --- a/pkg/common/types_test.go +++ b/pkg/common/types_test.go @@ -87,6 +87,7 @@ func TestRetinaEndpointCommonFromAPI(t *testing.T) { annotations: map[string]string{ RetinaPodAnnotation: RetinaPodAnnotationValue, }, + nodeIP: hostIP, }, }, { @@ -140,6 +141,7 @@ func TestRetinaEndpointCommonFromAPI(t *testing.T) { annotations: map[string]string{ RetinaPodAnnotation: RetinaPodAnnotationValue, }, + nodeIP: hostIP, }, }, } diff --git a/pkg/plugin/dropreason/dropreason_linux_test.go b/pkg/plugin/dropreason/dropreason_linux_test.go index 6e59e1d2af..b57924901a 100644 --- a/pkg/plugin/dropreason/dropreason_linux_test.go +++ b/pkg/plugin/dropreason/dropreason_linux_test.go @@ -179,11 +179,10 @@ func TestDropReasonRun_Error(t *testing.T) { // Create a context with a short timeout for testing purposes ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + errCh := make(chan error, 1) // Start the drop reason routine in a goroutine go func() { - if err := dr.run(ctx); err != nil { - t.Fatalf("unexpected error: %v", err) - } + errCh <- dr.run(ctx) }() // Wait for a short period of time for the routine to start @@ -191,6 +190,9 @@ func TestDropReasonRun_Error(t *testing.T) { cancel() ticker.Stop() + if err := <-errCh; err != nil { + t.Fatalf("unexpected error: %v", err) + } } func TestDropReasonRun(t *testing.T) { @@ -241,11 +243,10 @@ func TestDropReasonRun(t *testing.T) { // create a ticker with a short interval for testing purposes ticker := time.NewTicker(2 * time.Second) + errCh := make(chan error, 1) // Start the drop reason routine in a goroutine go func() { - if err := dr.run(ctx); err != nil { - t.Fatalf("unexpected error: %v", err) - } + errCh <- dr.run(ctx) }() // Wait for a short period of time for the routine to start @@ -253,6 +254,9 @@ func TestDropReasonRun(t *testing.T) { cancel() ticker.Stop() + if err := <-errCh; err != nil { + t.Fatalf("unexpected error: %v", err) + } } func TestDropReasonReadDataPodLevelEnabled(t *testing.T) { @@ -298,8 +302,8 @@ func TestDropReasonReadDataPodLevelEnabled(t *testing.T) { dr.readEventArrayData() }() + dr.wg.Add(1) go func() { - dr.wg.Add(1) dr.processRecord(ctx, 0) }() diff --git a/pkg/plugin/dropreason/mocks/mock_types_linux.go b/pkg/plugin/dropreason/mocks/mock_types_linux.go index 21f3fda4e6..7f49d93498 100644 --- a/pkg/plugin/dropreason/mocks/mock_types_linux.go +++ b/pkg/plugin/dropreason/mocks/mock_types_linux.go @@ -21,7 +21,6 @@ import ( type MockIMapIterator struct { ctrl *gomock.Controller recorder *MockIMapIteratorMockRecorder - isgomock struct{} } // MockIMapIteratorMockRecorder is the mock recorder for MockIMapIterator. @@ -73,7 +72,6 @@ func (mr *MockIMapIteratorMockRecorder) Next(keyOut, valueOut any) *gomock.Call type MockIMap struct { ctrl *gomock.Controller recorder *MockIMapMockRecorder - isgomock struct{} } // MockIMapMockRecorder is the mock recorder for MockIMap. @@ -125,7 +123,6 @@ func (mr *MockIMapMockRecorder) Iterate() *gomock.Call { type MockIPerfReader struct { ctrl *gomock.Controller recorder *MockIPerfReaderMockRecorder - isgomock struct{} } // MockIPerfReaderMockRecorder is the mock recorder for MockIPerfReader. diff --git a/pkg/plugin/dropreason/types_linux.go b/pkg/plugin/dropreason/types_linux.go index 5db5c363e2..5e2129e886 100644 --- a/pkg/plugin/dropreason/types_linux.go +++ b/pkg/plugin/dropreason/types_linux.go @@ -90,7 +90,7 @@ type ( // Interface to https://pkg.go.dev/github.com/cilium/ebpf#Map. // Added for unit tests. // -//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types.go -package=dropreason . IMap IMapIterator IPerfReader +//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types_linux.go -package=dropreason . IMap IMapIterator IPerfReader type IMapIterator interface { Next(keyOut interface{}, valueOut interface{}) bool Err() error diff --git a/pkg/plugin/packetparser/mocks/mock_types_linux.go b/pkg/plugin/packetparser/mocks/mock_types_linux.go index 0019773e74..65478d8b5f 100644 --- a/pkg/plugin/packetparser/mocks/mock_types_linux.go +++ b/pkg/plugin/packetparser/mocks/mock_types_linux.go @@ -3,7 +3,7 @@ // // Generated by this command: // -// mockgen -source=types_linux.go -destination=mocks/mock_types_linux.go -package=mocks +// mockgen -source=types_linux.go -destination=mocks/mock_types_linux.go -package=mocks -exclude_interfaces=perfReader // // Package mocks is a generated GoMock package. @@ -12,7 +12,6 @@ package mocks import ( reflect "reflect" - perf "github.com/cilium/ebpf/perf" tc "github.com/florianl/go-tc" netlink "github.com/mdlayher/netlink" gomock "go.uber.org/mock/gomock" @@ -184,55 +183,3 @@ func (mr *MocknltcMockRecorder) SetOption(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetOption", reflect.TypeOf((*Mocknltc)(nil).SetOption), arg0, arg1) } - -// MockperfReader is a mock of perfReader interface. -type MockperfReader struct { - ctrl *gomock.Controller - recorder *MockperfReaderMockRecorder -} - -// MockperfReaderMockRecorder is the mock recorder for MockperfReader. -type MockperfReaderMockRecorder struct { - mock *MockperfReader -} - -// NewMockperfReader creates a new mock instance. -func NewMockperfReader(ctrl *gomock.Controller) *MockperfReader { - mock := &MockperfReader{ctrl: ctrl} - mock.recorder = &MockperfReaderMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockperfReader) EXPECT() *MockperfReaderMockRecorder { - return m.recorder -} - -// Close mocks base method. -func (m *MockperfReader) Close() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 -} - -// Close indicates an expected call of Close. -func (mr *MockperfReaderMockRecorder) Close() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockperfReader)(nil).Close)) -} - -// Read mocks base method. -func (m *MockperfReader) Read() (perf.Record, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Read") - ret0, _ := ret[0].(perf.Record) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Read indicates an expected call of Read. -func (mr *MockperfReaderMockRecorder) Read() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockperfReader)(nil).Read)) -} diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go index 311f31ea4e..2f54dbba58 100644 --- a/pkg/plugin/packetparser/packetparser_linux_test.go +++ b/pkg/plugin/packetparser/packetparser_linux_test.go @@ -10,6 +10,7 @@ import ( "fmt" "os" "path" + "reflect" "runtime" "sync" "testing" @@ -17,7 +18,6 @@ import ( v1 "github.com/cilium/cilium/pkg/hubble/api/v1" "github.com/cilium/ebpf" - "github.com/cilium/ebpf/perf" tc "github.com/florianl/go-tc" nl "github.com/mdlayher/netlink" kcfg "github.com/microsoft/retina/pkg/config" @@ -33,30 +33,50 @@ import ( "go.uber.org/mock/gomock" ) -type perfReaderAdapter struct { - mock *mocks.MockperfReader +// mockPerfReader is a gomock-based mock for the perfReader interface. +// Defined here (not in mocks/) because perfReader uses the unexported perfRecord type. +type mockPerfReader struct { + ctrl *gomock.Controller + recorder *mockPerfReaderRecorder } -func (p *perfReaderAdapter) Read() (perfRecord, error) { - rec, err := p.mock.Read() - if err != nil { - return perfRecord{}, fmt.Errorf("failed to read perf record: %w", err) - } - return perfRecord{ - CPU: rec.CPU, - LostSamples: rec.LostSamples, - RawSample: rec.RawSample, - Remaining: rec.Remaining, - }, nil +type mockPerfReaderRecorder struct { + mock *mockPerfReader } -func (p *perfReaderAdapter) Close() error { - if err := p.mock.Close(); err != nil { - return fmt.Errorf("failed to close perf reader: %w", err) - } - return nil +func newMockPerfReader(ctrl *gomock.Controller) *mockPerfReader { + m := &mockPerfReader{ctrl: ctrl} + m.recorder = &mockPerfReaderRecorder{m} + return m +} + +func (m *mockPerfReader) EXPECT() *mockPerfReaderRecorder { return m.recorder } + +func (m *mockPerfReader) Read() (perfRecord, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Read") + rec, _ := ret[0].(perfRecord) + err, _ := ret[1].(error) + return rec, err +} + +func (mr *mockPerfReaderRecorder) Read() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*mockPerfReader)(nil).Read)) +} + +func (m *mockPerfReader) Close() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Close") + err, _ := ret[0].(error) + return err } +func (mr *mockPerfReaderRecorder) Close() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*mockPerfReader)(nil).Close)) +} + +var errTestRead = errors.New("error") + var ( cfgPodLevelEnabled = &kcfg.Config{ EnablePodLevel: true, @@ -314,8 +334,8 @@ func TestReadData_Error(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mperf := mocks.NewMockperfReader(ctrl) - mperf.EXPECT().Read().Return(perf.Record{}, errors.New("error")).AnyTimes() + mperf := newMockPerfReader(ctrl) + mperf.EXPECT().Read().Return(perfRecord{}, errTestRead).AnyTimes() menricher := enricher.NewMockEnricherInterface(ctrl) //nolint:typecheck menricher.EXPECT().Write(gomock.Any()).Times(0) @@ -323,12 +343,12 @@ func TestReadData_Error(t *testing.T) { p := &packetParser{ cfg: cfgPodLevelEnabled, l: log.Logger().Named("test"), - reader: &perfReaderAdapter{mock: mperf}, + reader: mperf, } p.readData() // Lost samples. - mperf.EXPECT().Read().Return(perf.Record{ + mperf.EXPECT().Read().Return(perfRecord{ LostSamples: 1, }, nil).AnyTimes() p.readData() @@ -348,12 +368,12 @@ func TestReadDataPodLevelEnabled(t *testing.T) { DstPort: uint16(443), } bytes, _ := json.Marshal(bpfEvent) - record := perf.Record{ + record := perfRecord{ LostSamples: 0, RawSample: bytes, } - mperf := mocks.NewMockperfReader(ctrl) + mperf := newMockPerfReader(ctrl) mperf.EXPECT().Read().Return(record, nil).MinTimes(1) menricher := enricher.NewMockEnricherInterface(ctrl) //nolint:typecheck @@ -362,7 +382,7 @@ func TestReadDataPodLevelEnabled(t *testing.T) { p := &packetParser{ cfg: cfgPodLevelEnabled, l: log.Logger().Named("test"), - reader: &perfReaderAdapter{mock: mperf}, + reader: mperf, enricher: menricher, recordsChannel: make(chan perfRecord, buffer), } @@ -428,12 +448,12 @@ func TestStartWithDataAggregationLevelLow(t *testing.T) { } bytes, err := json.Marshal(bpfEvent) // nolint:musttag // ignore require.NoError(t, err) - record := perf.Record{ + record := perfRecord{ LostSamples: 0, RawSample: bytes, } - mockReader := mocks.NewMockperfReader(ctrl) + mockReader := newMockPerfReader(ctrl) mockReader.EXPECT().Read().Return(record, nil).MinTimes(1) getQdisc = func(_ nltc) qdisc { @@ -460,7 +480,7 @@ func TestStartWithDataAggregationLevelLow(t *testing.T) { cfg: cfgDataAggregationLevelLow, l: log.Logger().Named("test"), objs: pObj, - reader: &perfReaderAdapter{mock: mockReader}, + reader: mockReader, recordsChannel: make(chan perfRecord, buffer), interfaceLockMap: &sync.Map{}, endpointIngressInfo: &ebpf.ProgramInfo{ @@ -507,12 +527,12 @@ func TestStartWithDataAggregationLevelHigh(t *testing.T) { } bytes, err := json.Marshal(bpfEvent) // nolint:musttag // ignore require.NoError(t, err) - record := perf.Record{ + record := perfRecord{ LostSamples: 0, RawSample: bytes, } - mockReader := mocks.NewMockperfReader(ctrl) + mockReader := newMockPerfReader(ctrl) mockReader.EXPECT().Read().Return(record, nil).MinTimes(1) getQdisc = func(_ nltc) qdisc { @@ -539,7 +559,7 @@ func TestStartWithDataAggregationLevelHigh(t *testing.T) { cfg: cfgDataAggregationLevelHigh, l: log.Logger().Named("test"), objs: pObj, - reader: &perfReaderAdapter{mock: mockReader}, + reader: mockReader, recordsChannel: make(chan perfRecord, buffer), interfaceLockMap: &sync.Map{}, endpointIngressInfo: &ebpf.ProgramInfo{ diff --git a/pkg/plugin/packetparser/types_linux.go b/pkg/plugin/packetparser/types_linux.go index fa7f7d78ee..631e62b34b 100644 --- a/pkg/plugin/packetparser/types_linux.go +++ b/pkg/plugin/packetparser/types_linux.go @@ -101,7 +101,7 @@ type attachmentValue struct { tcxEgressLink link.Link } -//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types_linux.go -package=mocks +//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -source=types_linux.go -destination=mocks/mock_types_linux.go -package=mocks -exclude_interfaces=perfReader // tc qdisc interface type qdisc interface { diff --git a/test/utsummary/main.go b/test/utsummary/main.go index 3faff60442..647551262e 100644 --- a/test/utsummary/main.go +++ b/test/utsummary/main.go @@ -68,6 +68,10 @@ func run(r io.Reader) (msg string, failures bool, err error) { // Stores output produced by each test. testOutputs := map[string][]string{} + // Tracks packages that had at least one test-level event, + // used to distinguish build failures from normal test failures. + pkgHasTests := map[string]bool{} + start := time.Now() for scanner.Scan() { // When the build fails, go test -json doesn't emit a valid JSON value, only @@ -86,10 +90,23 @@ func run(r io.Reader) (msg string, failures bool, err error) { // The Test field, if non-empty, specifies the test, example, or benchmark // function that caused the event. Events for the overall package test do // not set Test. + if event.Test != "" { + pkgHasTests[event.Package] = true + } if event.Action == "fail" && event.Test != "" { failedTests = append(failedTests, testpath) } + // A package-level fail with no Test field and no test-level events + // indicates a build failure (e.g. [build failed]). These must be + // tracked as failures so that broken packages are not silently ignored. + // If the package had test-level events, the package fail is just a + // summary of individual test failures (already counted above). + if event.Action == "fail" && event.Test == "" && !pkgHasTests[event.Package] { + failedTests = append(failedTests, event.Package+" [build failed]") + counts["fail"]++ + } + if event.Action == "output" { if *verbose { fmt.Print(event.Output) @@ -97,9 +114,9 @@ func run(r io.Reader) (msg string, failures bool, err error) { testOutputs[testpath] = append(testOutputs[testpath], event.Output) } - // We don't want to count package passes/fails because these don't - // represent specific tests being run. However, skips of an entire package - // are not duplicated with individual test skips. + // We don't want to count package passes because these don't represent + // specific tests being run. However, skips of an entire package are not + // duplicated with individual test skips. if event.Test != "" || event.Action == "skip" { counts[event.Action]++ } From 6a6f2a76bfb0aa6f56d0f6a36f1ca7ce5e1ccf35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:52:36 -0400 Subject: [PATCH 281/448] deps: bump actions/setup-go from 6.3.0 to 6.4.0 (#2149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.3.0 to 6.4.0.
Release notes

Sourced from actions/setup-go's releases.

v6.4.0

What's Changed

Enhancement

Dependency update

Documentation update

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.4.0

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/goreleaser.yaml | 4 ++-- .github/workflows/images.yaml | 12 ++++++------ .github/workflows/perf-template.yaml | 2 +- .github/workflows/release-images.yaml | 10 +++++----- .github/workflows/scale-test.yaml | 2 +- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/test.yaml | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index f02f140c60..0ea1f22e50 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -36,7 +36,7 @@ jobs: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - name: Initialize CodeQL diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 6c23650830..769992b03b 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -90,7 +90,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index db8c28535d..1cab442154 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - name: Build golangci-lint diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 7cf9cd4bb5..f27bb5603e 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - name: Install Syft @@ -49,7 +49,7 @@ jobs: with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - name: Install Syft diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 8c7fb41682..4765af92e1 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -48,7 +48,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -91,7 +91,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -213,7 +213,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -266,7 +266,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -318,7 +318,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -403,7 +403,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index f7ceae2b83..9929072e36 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -52,7 +52,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index bb048eab86..ea25908a25 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -32,7 +32,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -70,7 +70,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -182,7 +182,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -230,7 +230,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version @@ -276,7 +276,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/scale-test.yaml b/.github/workflows/scale-test.yaml index 4c7acb6037..36f0eefd18 100644 --- a/.github/workflows/scale-test.yaml +++ b/.github/workflows/scale-test.yaml @@ -72,7 +72,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod - run: go version diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 1268c5d87a..1fb2150f93 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 716c4423e5..8f836a9019 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -25,7 +25,7 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod From f8d90fd5a8d2b1e38ec2ce1c952a9f66cc02e603 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 1 Apr 2026 12:44:43 -0400 Subject: [PATCH 282/448] test(ebpf): add eBPF program unit tests via BPF_PROG_TEST_RUN (#2049) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Add an eBPF program unit test framework that executes compiled eBPF bytecode in the kernel using `BPF_PROG_TEST_RUN` (`prog.Run()` in cilium/ebpf). This validates actual kernel-side packet parsing logic rather than mocking the Go wrapper layer, catching bugs like wrong offsets, missing bounds checks, or incorrect flag handling that would otherwise only surface at runtime in a cluster. **Shared test infrastructure** (`pkg/plugin/ebpftest/`): - `helpers.go` — privilege checks, map pinning removal, generic perf event reader, IP/port byte-order helpers, LPM trie filter map population, program runner - `packet.go` — TCP/UDP/ICMP/ARP packet construction via gopacket with configurable flags, timestamps, and payloads **Packetparser tests** (`pkg/plugin/packetparser/packetparser_ebpf_test.go`) — 25 test functions covering: - **Packet parsing**: TCP flags (all 9 combinations), TCP timestamps, UDP, observation points, packet bytes field - **Filter map**: IP matching produces events, missing IPs produce none - **Edge cases**: runt packets, truncated IP/TCP headers, non-IPv4 (ARP/IPv6), ICMP - **Conntrack perf events**: `is_reply` across SYN/SYN-ACK/ACK, traffic direction per observation point, conntrack metrics counters, HIGH aggregation suppression, `previously_observed_*` fields - **Conntrack map state** (direct map reads): entry field initialization after SYN, flag bitmask accumulation across packets, reply packets updating RX-direction fields, `is_direction_unknown` for mid-stream connections, since-last-report counter accumulation and reset on FIN, lifetime metadata counters with `ENABLE_CONNTRACK_METRICS`, eviction time extension from SYN timeout to established - **Recompilation variants**: custom `dynamic.h` via `loader.CompileEbpf` for `DATA_AGGREGATION_LEVEL=HIGH` and `ENABLE_CONNTRACK_METRICS=1` **CI** (`.github/workflows/test-ebpf.yaml`): matrix strategy on amd64 (`ubuntu-latest`) and arm64 (`ubuntu-24.04-arm`), compiles eBPF via `go generate`, runs tests with `sudo`. **Makefile**: `make test-ebpf` target. ## Related Issue Partially addresses #876 — adds unit test coverage for packetparser eBPF programs. Remaining plugins (dropreason, dns, packetforward, etc.) can follow the same framework. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed All 25 eBPF tests pass locally on Linux amd64 with kernel 6.14.0: ``` === RUN TestEndpointIngressFilter_TCP PASS (0.27s) === RUN TestAllObservationPoints PASS (0.19s) === RUN TestTCPFlags PASS (0.19s) === RUN TestTCPTimestamps PASS (0.18s) === RUN TestUDPPacket PASS (0.17s) === RUN TestFilterMapFiltering PASS (0.68s) === RUN TestNonTCPUDP_NoEvent PASS (0.68s) === RUN TestNonIPv4_NoEvent PASS (1.17s) === RUN TestMalformedPackets PASS (0.68s) === RUN TestReturnValue PASS (0.57s) === RUN TestPacketBytesField PASS (0.18s) === RUN TestConntrackMapUpdated PASS (0.18s) === RUN TestConntrackIsReply PASS (0.17s) === RUN TestConntrackTrafficDirection PASS (0.18s) === RUN TestConntrackMetricsEnabled PASS (0.55s) === RUN TestHighAggregationLevel PASS (0.95s) === RUN TestHighAggregationPreviouslyObserved PASS (0.66s) === RUN TestConntrackEntryCreation PASS (0.20s) === RUN TestConntrackFlagAccumulation PASS (0.19s) === RUN TestConntrackReplyUpdatesEntry PASS (0.19s) === RUN TestConntrackDirectionUnknown PASS (0.17s) === RUN TestConntrackSinceLastReportAccumulation PASS (0.85s) === RUN TestConntrackCounterResetOnReport PASS (0.86s) === RUN TestConntrackMetadataCountersInMap PASS (0.55s) === RUN TestConntrackEvictionTimeExtended PASS (0.18s) ok github.com/microsoft/retina/pkg/plugin/packetparser 14.127s ``` Lint passes cleanly (`make lint` — 0 new issues). Existing unit tests unaffected (different build tag: `ebpf` vs `unit`). ## Additional Notes - Tests use `//go:build ebpf && linux` — they do **not** run during `make test` - Requires `CAP_BPF` + `CAP_NET_ADMIN` (or root) and Linux kernel >= 5.x - The `ebpftest` package is designed for reuse by other plugin tests (dropreason, dns, etc.) - Recompilation tests use `loader.CompileEbpf` (same as production) and require clang --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- .github/workflows/test-ebpf.yaml | 49 + Makefile | 4 + pkg/plugin/ebpftest/helpers.go | 195 +++ pkg/plugin/ebpftest/packet.go | 265 ++++ .../packetparser/packetparser_ebpf_test.go | 1190 +++++++++++++++++ 5 files changed, 1703 insertions(+) create mode 100644 .github/workflows/test-ebpf.yaml create mode 100644 pkg/plugin/ebpftest/helpers.go create mode 100644 pkg/plugin/ebpftest/packet.go create mode 100644 pkg/plugin/packetparser/packetparser_ebpf_test.go diff --git a/.github/workflows/test-ebpf.yaml b/.github/workflows/test-ebpf.yaml new file mode 100644 index 0000000000..4503f4aa0d --- /dev/null +++ b/.github/workflows/test-ebpf.yaml @@ -0,0 +1,49 @@ +name: eBPF Program Tests +on: + push: + branches: [main] + paths: + - 'pkg/plugin/**/_cprog/**' + - 'pkg/plugin/**/*_ebpf_test.go' + - 'pkg/plugin/ebpftest/**' + pull_request: + branches: [main] + paths: + - 'pkg/plugin/**/_cprog/**' + - 'pkg/plugin/**/*_ebpf_test.go' + - 'pkg/plugin/ebpftest/**' + workflow_dispatch: + +permissions: + contents: read + +jobs: + ebpf-tests: + strategy: + matrix: + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + + - name: Install clang and llvm-strip + run: | + sudo apt-get update + sudo apt-get install -y clang llvm + + - name: Compile eBPF programs + run: | + GOARCH=${{ matrix.arch }} go generate ./pkg/plugin/... + + - name: Run eBPF program tests + run: | + sudo $(which go) test -tags=ebpf -v -count=1 ./pkg/plugin/... diff --git a/Makefile b/Makefile index d335e21dff..a49bace34d 100644 --- a/Makefile +++ b/Makefile @@ -459,6 +459,10 @@ test: # Run unit tests. go build -o test-summary ./test/utsummary/main.go bash -o pipefail -c 'KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use -p path)" go test -tags=unit,dashboard -skip=TestE2E* -coverprofile=coverage.out -v -json ./... | ./test-summary --progress --verbose' +.PHONY: test-ebpf +test-ebpf: # Run eBPF program tests (requires root/CAP_BPF). + sudo $$(which go) test -tags=ebpf -v -count=1 ./pkg/plugin/... + coverage: # Code coverage. # go generate ./... && go test -tags=unit -coverprofile=coverage.out.tmp ./... cat coverage.out | grep -Ev '_bpf\.go|_bpfel_x86\.go|_bpfel_arm64\.go|_generated\.go|mock_' > coveragenew.out diff --git a/pkg/plugin/ebpftest/helpers.go b/pkg/plugin/ebpftest/helpers.go new file mode 100644 index 0000000000..d4fba5a9f1 --- /dev/null +++ b/pkg/plugin/ebpftest/helpers.go @@ -0,0 +1,195 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build ebpf && linux + +package ebpftest + +import ( + "bytes" + "encoding/binary" + "errors" + "net" + "os" + "testing" + "time" + "unsafe" + + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/perf" + "github.com/stretchr/testify/require" + "golang.org/x/sys/unix" +) + +// RequirePrivileged skips the test if the current process lacks BPF privileges. +// It checks for CAP_BPF or CAP_SYS_ADMIN in the effective capability set. +func RequirePrivileged(t *testing.T) { + t.Helper() + + if os.Geteuid() == 0 { + return // root has all capabilities + } + + var hdr unix.CapUserHeader + var data [2]unix.CapUserData + hdr.Version = unix.LINUX_CAPABILITY_VERSION_3 + + if err := unix.Capget(&hdr, &data[0]); err != nil { + t.Skipf("skipping eBPF test: cannot query capabilities: %v", err) + return + } + + if !hasEffectiveCap(data, unix.CAP_BPF) && !hasEffectiveCap(data, unix.CAP_SYS_ADMIN) { + t.Skip("skipping eBPF test: need CAP_BPF or CAP_SYS_ADMIN") + } +} + +// hasEffectiveCap checks whether the given capability is set in the effective set. +func hasEffectiveCap(data [2]unix.CapUserData, cap uintptr) bool { + i := cap / 32 + bit := uint32(1) << (cap % 32) + return data[i].Effective&bit != 0 +} + +// RemoveMapPinning sets Pinning to PinNone on all maps in the collection spec. +// This is required because embedded objects may have LIBBPF_PIN_BY_NAME which +// would fail in test environments without /sys/fs/bpf access. +func RemoveMapPinning(spec *ebpf.CollectionSpec) { + for _, m := range spec.Maps { + m.Pinning = ebpf.PinNone + } +} + +// ReadPerfEvent reads one perf record from the reader within the given timeout, +// decodes it into T using binary.Read (little-endian), and returns it. +// Returns (zero, false) if the deadline expires without an event. +func ReadPerfEvent[T any](t *testing.T, reader *perf.Reader, timeout time.Duration) (T, bool) { + t.Helper() + + reader.SetDeadline(time.Now().Add(timeout)) + + record, err := reader.Read() + var zero T + if errors.Is(err, os.ErrDeadlineExceeded) { + return zero, false + } + require.NoError(t, err) + require.Zero(t, record.LostSamples, "perf reader lost samples") + + var event T + err = binary.Read(bytes.NewReader(record.RawSample), binary.LittleEndian, &event) + require.NoError(t, err, "failed to decode perf event") + + return event, true +} + +// AssertNoPerfEvent asserts that no perf event is emitted within the given timeout. +func AssertNoPerfEvent(t *testing.T, reader *perf.Reader, timeout time.Duration) { + t.Helper() + + reader.SetDeadline(time.Now().Add(timeout)) + + _, err := reader.Read() + if errors.Is(err, os.ErrDeadlineExceeded) { + return // expected: no event + } + if err != nil { + return // reader error is acceptable for "no event" assertion + } + t.Fatal("expected no perf event but got one") +} + +// IPToNative converts an IP string to its uint32 representation as stored by +// eBPF programs. Programs store ip->saddr directly from the packet (network +// byte order), which on a LE machine is the raw 4 bytes interpreted as a LE uint32. +func IPToNative(ipStr string) uint32 { + ip := net.ParseIP(ipStr).To4() + return *(*uint32)(unsafe.Pointer(&ip[0])) +} + +// PortToNetwork converts a host port number to the byte order used by eBPF +// programs. Programs store tcp->source / tcp->dest directly from the packet +// header (big-endian), then perf events are decoded as LE by binary.Read. +func PortToNetwork(port uint16) uint16 { + var buf [2]byte + binary.BigEndian.PutUint16(buf[:], port) + return binary.LittleEndian.Uint16(buf[:]) +} + +// LPMTrieKey represents the key for the retina_filter LPM trie map. +// This struct matches the layout generated by bpf2go for all plugins +// that use the shared retina_filter map. +type LPMTrieKey struct { + Prefixlen uint32 + Data uint32 +} + +// PopulateFilterMap inserts IPs into a retina_filter LPM trie map so that +// the eBPF program's lookup() function matches them. +func PopulateFilterMap(t *testing.T, filterMap *ebpf.Map, ips ...net.IP) { + t.Helper() + for _, ip := range ips { + ipBytes := ip.To4() + require.NotNil(t, ipBytes, "expected IPv4 address") + + key := LPMTrieKey{ + Prefixlen: 32, + Data: *(*uint32)(unsafe.Pointer(&ipBytes[0])), + } + val := uint8(1) + err := filterMap.Put(key, val) + require.NoError(t, err) + } +} + +// RunProgram executes an eBPF program via prog.Run() and returns the retval. +// Use this for TC classifier programs where perf events fire during Run(). +func RunProgram(t *testing.T, prog *ebpf.Program, pkt []byte) uint32 { + t.Helper() + ret, err := prog.Run(&ebpf.RunOptions{ + Data: pkt, + }) + require.NoError(t, err) + return ret +} + +// RunSocketFilter executes a socket filter program via prog.Test(). +// +// BPF_PROG_TEST_RUN for socket filters calls eth_type_trans(), which +// strips the first 14 bytes (Ethernet header) from the packet data. +// This function prepends a 14-byte dummy so the kernel strips that +// instead of the real Ethernet header, keeping bpf_skb_load_bytes +// offsets consistent with production. +// +// Perf events do NOT fire during Test() — use ReadPerCPUMap to read +// results from a per-CPU scratch map instead. +func RunSocketFilter(t *testing.T, prog *ebpf.Program, pkt []byte) uint32 { + t.Helper() + padded := append(make([]byte, 14), pkt...) + ret, _, err := prog.Test(padded) + require.NoError(t, err) + return ret +} + +// ReadPerCPUMap reads a per-CPU array map at the given key and returns the +// first entry with a non-zero first 8 bytes (typically a timestamp field). +// This is the standard way to read results from BPF programs that use a +// per-CPU scratch map during BPF_PROG_TEST_RUN (where perf events don't fire). +func ReadPerCPUMap[T any](t *testing.T, m *ebpf.Map, key uint32) (T, bool) { + t.Helper() + var values []T + err := m.Lookup(key, &values) + require.NoError(t, err, "failed to read per-CPU map") + + // Find the CPU that ran the program by looking for a non-zero timestamp + // (the first 8 bytes of the struct). + for _, v := range values { + raw := (*[8]byte)(unsafe.Pointer(&v)) + ts := binary.LittleEndian.Uint64(raw[:]) + if ts != 0 { + return v, true + } + } + var zero T + return zero, false +} diff --git a/pkg/plugin/ebpftest/packet.go b/pkg/plugin/ebpftest/packet.go new file mode 100644 index 0000000000..061ca2c6d8 --- /dev/null +++ b/pkg/plugin/ebpftest/packet.go @@ -0,0 +1,265 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build ebpf && linux + +package ebpftest + +import ( + "net" + + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" +) + +var ( + // Default MAC addresses for test packets (arbitrary, eBPF programs don't inspect MACs). + DefaultSrcMAC = net.HardwareAddr{0x00, 0x00, 0x5e, 0x00, 0x53, 0x01} + DefaultDstMAC = net.HardwareAddr{0x00, 0x00, 0x5e, 0x00, 0x53, 0x02} +) + +// TCPPacketOpts configures a test TCP packet. +type TCPPacketOpts struct { + SrcIP, DstIP net.IP + SrcPort, DstPort uint16 + SYN, ACK, FIN bool + RST, PSH, URG bool + ECE, CWR bool + SeqNum, AckNum uint32 + TSval, TSecr uint32 // Zero means omit TCP timestamp option. + PayloadSize int +} + +// BuildTCPPacket constructs a valid Ethernet + IPv4 + TCP packet. +func BuildTCPPacket(opts TCPPacketOpts) []byte { + eth := &layers.Ethernet{ + SrcMAC: DefaultSrcMAC, + DstMAC: DefaultDstMAC, + EthernetType: layers.EthernetTypeIPv4, + } + + ip := &layers.IPv4{ + Version: 4, + IHL: 5, + TTL: 64, + Protocol: layers.IPProtocolTCP, + SrcIP: opts.SrcIP.To4(), + DstIP: opts.DstIP.To4(), + } + + tcp := &layers.TCP{ + SrcPort: layers.TCPPort(opts.SrcPort), + DstPort: layers.TCPPort(opts.DstPort), + SYN: opts.SYN, + ACK: opts.ACK, + FIN: opts.FIN, + RST: opts.RST, + PSH: opts.PSH, + URG: opts.URG, + ECE: opts.ECE, + CWR: opts.CWR, + Seq: opts.SeqNum, + Ack: opts.AckNum, + Window: 65535, + } + + if opts.TSval != 0 || opts.TSecr != 0 { + tcp.Options = append(tcp.Options, layers.TCPOption{ + OptionType: layers.TCPOptionKindTimestamps, + OptionLength: 10, + OptionData: []byte{ + byte(opts.TSval >> 24), byte(opts.TSval >> 16), byte(opts.TSval >> 8), byte(opts.TSval), + byte(opts.TSecr >> 24), byte(opts.TSecr >> 16), byte(opts.TSecr >> 8), byte(opts.TSecr), + }, + }) + } + + tcp.SetNetworkLayerForChecksum(ip) + + payload := make([]byte, opts.PayloadSize) + + buf := gopacket.NewSerializeBuffer() + serializeOpts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + err := gopacket.SerializeLayers(buf, serializeOpts, + eth, ip, tcp, gopacket.Payload(payload)) + if err != nil { + panic("failed to serialize TCP packet: " + err.Error()) + } + + return buf.Bytes() +} + +// UDPPacketOpts configures a test UDP packet. +type UDPPacketOpts struct { + SrcIP, DstIP net.IP + SrcPort, DstPort uint16 + Payload []byte // Raw payload bytes. If nil, PayloadSize zero bytes are used. + PayloadSize int // Ignored when Payload is set. +} + +// BuildUDPPacket constructs a valid Ethernet + IPv4 + UDP packet. +func BuildUDPPacket(opts UDPPacketOpts) []byte { + eth := &layers.Ethernet{ + SrcMAC: DefaultSrcMAC, + DstMAC: DefaultDstMAC, + EthernetType: layers.EthernetTypeIPv4, + } + + ip := &layers.IPv4{ + Version: 4, + IHL: 5, + TTL: 64, + Protocol: layers.IPProtocolUDP, + SrcIP: opts.SrcIP.To4(), + DstIP: opts.DstIP.To4(), + } + + udp := &layers.UDP{ + SrcPort: layers.UDPPort(opts.SrcPort), + DstPort: layers.UDPPort(opts.DstPort), + } + + udp.SetNetworkLayerForChecksum(ip) + + payload := opts.Payload + if payload == nil { + payload = make([]byte, opts.PayloadSize) + } + + buf := gopacket.NewSerializeBuffer() + serializeOpts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + err := gopacket.SerializeLayers(buf, serializeOpts, + eth, ip, udp, gopacket.Payload(payload)) + if err != nil { + panic("failed to serialize UDP packet: " + err.Error()) + } + + return buf.Bytes() +} + + +// BuildNonIPPacket constructs an Ethernet frame with the given EtherType and a small payload. +// Useful for testing that eBPF programs correctly skip non-IPv4 traffic. +func BuildNonIPPacket(etherType layers.EthernetType) []byte { + eth := &layers.Ethernet{ + SrcMAC: DefaultSrcMAC, + DstMAC: DefaultDstMAC, + EthernetType: etherType, + } + + buf := gopacket.NewSerializeBuffer() + serializeOpts := gopacket.SerializeOptions{FixLengths: true} + + // Add enough payload to be a valid-looking frame. + err := gopacket.SerializeLayers(buf, serializeOpts, + eth, gopacket.Payload(make([]byte, 46))) + if err != nil { + panic("failed to serialize non-IP packet: " + err.Error()) + } + + return buf.Bytes() +} + +// BuildRuntPacket returns a byte slice shorter than 14 bytes (Ethernet header size). +func BuildRuntPacket() []byte { + return []byte{0x00, 0x00, 0x5e, 0x00, 0x53, 0x01, 0x00, 0x00, 0x5e, 0x00} +} + +// BuildTruncatedIPPacket returns a valid Ethernet header followed by a truncated IPv4 header. +func BuildTruncatedIPPacket() []byte { + eth := &layers.Ethernet{ + SrcMAC: DefaultSrcMAC, + DstMAC: DefaultDstMAC, + EthernetType: layers.EthernetTypeIPv4, + } + + buf := gopacket.NewSerializeBuffer() + serializeOpts := gopacket.SerializeOptions{FixLengths: true} + + err := gopacket.SerializeLayers(buf, serializeOpts, eth) + if err != nil { + panic("failed to serialize ethernet header: " + err.Error()) + } + + // Append a truncated IPv4 header (only 10 bytes instead of minimum 20). + result := buf.Bytes() + result = append(result, []byte{0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06}...) + return result +} + +// BuildICMPPacket constructs a valid Ethernet + IPv4 + ICMP echo request packet. +func BuildICMPPacket(srcIP, dstIP net.IP) []byte { + eth := &layers.Ethernet{ + SrcMAC: DefaultSrcMAC, + DstMAC: DefaultDstMAC, + EthernetType: layers.EthernetTypeIPv4, + } + + ip := &layers.IPv4{ + Version: 4, + IHL: 5, + TTL: 64, + Protocol: layers.IPProtocolICMPv4, + SrcIP: srcIP.To4(), + DstIP: dstIP.To4(), + } + + icmp := &layers.ICMPv4{ + TypeCode: layers.CreateICMPv4TypeCode(layers.ICMPv4TypeEchoRequest, 0), + Id: 1, + Seq: 1, + } + + buf := gopacket.NewSerializeBuffer() + serializeOpts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + err := gopacket.SerializeLayers(buf, serializeOpts, + eth, ip, icmp, gopacket.Payload([]byte("ping"))) + if err != nil { + panic("failed to serialize ICMP packet: " + err.Error()) + } + + return buf.Bytes() +} + +// BuildTruncatedTCPPacket constructs an Ethernet + IPv4 header with a truncated TCP header. +func BuildTruncatedTCPPacket(srcIP, dstIP net.IP) []byte { + eth := &layers.Ethernet{ + SrcMAC: DefaultSrcMAC, + DstMAC: DefaultDstMAC, + EthernetType: layers.EthernetTypeIPv4, + } + + ip := &layers.IPv4{ + Version: 4, + IHL: 5, + TTL: 64, + Protocol: layers.IPProtocolTCP, + SrcIP: srcIP.To4(), + DstIP: dstIP.To4(), + } + + buf := gopacket.NewSerializeBuffer() + serializeOpts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true} + + err := gopacket.SerializeLayers(buf, serializeOpts, eth, ip) + if err != nil { + panic("failed to serialize IP header: " + err.Error()) + } + + // Append only 10 bytes of TCP header (minimum is 20). + result := buf.Bytes() + result = append(result, []byte{0x30, 0x39, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}...) + return result +} diff --git a/pkg/plugin/packetparser/packetparser_ebpf_test.go b/pkg/plugin/packetparser/packetparser_ebpf_test.go new file mode 100644 index 0000000000..6f3110b7c3 --- /dev/null +++ b/pkg/plugin/packetparser/packetparser_ebpf_test.go @@ -0,0 +1,1190 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build ebpf && linux + +package packetparser + +import ( + "context" + "fmt" + "net" + "os" + "os/exec" + "path" + "runtime" + "testing" + "time" + + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/perf" + "github.com/gopacket/gopacket/layers" + "github.com/microsoft/retina/pkg/loader" + "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/plugin/ebpftest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + // Observation points from conntrack.h + observationPointFromEndpoint = 0x00 + observationPointToEndpoint = 0x01 + observationPointFromNetwork = 0x02 + observationPointToNetwork = 0x03 + + // TC_ACT_UNSPEC is -1 in C, which becomes 0xFFFFFFFF as uint32. + tcActUnspec = 0xFFFFFFFF + + // Protocol numbers + protoTCP = 6 + protoUDP = 17 + + // Traffic directions from conntrack.h + trafficDirectionUnknown = 0x00 + trafficDirectionIngress = 0x01 + trafficDirectionEgress = 0x02 + + // perfReaderTimeout is how long to wait for a perf event. + perfReaderTimeout = 500 * time.Millisecond +) + +// loadTestObjects loads the packetparser eBPF programs and maps for testing. +func loadTestObjects(t *testing.T) (*packetparserObjects, *perf.Reader) { + t.Helper() + ebpftest.RequirePrivileged(t) + + spec, err := loadPacketparser() + require.NoError(t, err) + + ebpftest.RemoveMapPinning(spec) + + var objs packetparserObjects + err = spec.LoadAndAssign(&objs, nil) + require.NoError(t, err) + t.Cleanup(func() { objs.Close() }) + + reader, err := perf.NewReader(objs.RetinaPacketparserEvents, os.Getpagesize()*4) + require.NoError(t, err) + t.Cleanup(func() { reader.Close() }) + + return &objs, reader +} + +func TestEndpointIngressFilter_TCP(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.0.1") + dstIP := net.ParseIP("10.0.0.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 12345, + DstPort: 80, + SYN: true, + SeqNum: 1000, + }) + + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret, "expected TC_ACT_UNSPEC return value") + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + + assert.Equal(t, ebpftest.IPToNative("10.0.0.1"), event.SrcIp) + assert.Equal(t, ebpftest.IPToNative("10.0.0.2"), event.DstIp) + assert.Equal(t, ebpftest.PortToNetwork(12345), event.SrcPort) + assert.Equal(t, ebpftest.PortToNetwork(80), event.DstPort) + assert.Equal(t, uint8(protoTCP), event.Proto) + assert.Equal(t, uint8(observationPointFromEndpoint), event.ObservationPoint) + assert.NotZero(t, event.T_nsec, "timestamp should be set") + assert.Equal(t, uint32(len(pkt)), event.Bytes) + + // SYN flag should be set (bit 1) + assert.NotZero(t, event.Flags&0x02, "SYN flag should be set") +} + +func TestAllObservationPoints(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.1.1") + dstIP := net.ParseIP("10.0.1.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + tests := []struct { + name string + prog *ebpf.Program + expected uint8 + }{ + {"endpoint_ingress", objs.EndpointIngressFilter, observationPointFromEndpoint}, + {"endpoint_egress", objs.EndpointEgressFilter, observationPointToEndpoint}, + {"host_ingress", objs.HostIngressFilter, observationPointFromNetwork}, + {"host_egress", objs.HostEgressFilter, observationPointToNetwork}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 1111, + DstPort: 2222, + SYN: true, + }) + + ebpftest.RunProgram(t, tc.prog, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + assert.Equal(t, tc.expected, event.ObservationPoint) + }) + } +} + +func TestTCPFlags(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.2.1") + dstIP := net.ParseIP("10.0.2.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // TCP flags bitmask as computed by the eBPF program: + // fin=bit0, syn=bit1, rst=bit2, psh=bit3, ack=bit4, urg=bit5, ece=bit6, cwr=bit7 + tests := []struct { + name string + opts ebpftest.TCPPacketOpts + expected uint16 + }{ + { + name: "SYN", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1000, DstPort: 80, + SYN: true, + }, + expected: 0x02, // syn=bit1 + }, + { + name: "ACK", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1001, DstPort: 80, + ACK: true, + }, + expected: 0x10, // ack=bit4 + }, + { + name: "SYN+ACK", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1002, DstPort: 80, + SYN: true, ACK: true, + }, + expected: 0x12, // syn=bit1 | ack=bit4 + }, + { + name: "FIN", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1003, DstPort: 80, + FIN: true, ACK: true, + }, + expected: 0x11, // fin=bit0 | ack=bit4 + }, + { + name: "RST", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1004, DstPort: 80, + RST: true, + }, + expected: 0x04, // rst=bit2 + }, + { + name: "PSH+ACK", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1005, DstPort: 80, + PSH: true, ACK: true, + }, + expected: 0x18, // psh=bit3 | ack=bit4 + }, + { + name: "URG", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1006, DstPort: 80, + URG: true, + }, + expected: 0x20, // urg=bit5 + }, + { + name: "ECE", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1007, DstPort: 80, + ECE: true, + }, + expected: 0x40, // ece=bit6 + }, + { + name: "CWR", + opts: ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 1008, DstPort: 80, + CWR: true, + }, + expected: 0x80, // cwr=bit7 + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + pkt := ebpftest.BuildTCPPacket(tc.opts) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + assert.Equal(t, tc.expected, event.Flags, "TCP flags mismatch") + }) + } +} + +func TestTCPTimestamps(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.3.1") + dstIP := net.ParseIP("10.0.3.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + t.Run("with_timestamps", func(t *testing.T) { + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 5000, + DstPort: 443, + SYN: true, + TSval: 12345678, + TSecr: 87654321, + }) + + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + assert.Equal(t, uint32(12345678), event.TcpMetadata.Tsval) + assert.Equal(t, uint32(87654321), event.TcpMetadata.Tsecr) + }) + + t.Run("without_timestamps", func(t *testing.T) { + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 5001, + DstPort: 443, + SYN: true, + }) + + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + assert.Zero(t, event.TcpMetadata.Tsval, "TSval should be zero when no timestamp option") + assert.Zero(t, event.TcpMetadata.Tsecr, "TSecr should be zero when no timestamp option") + }) +} + +func TestUDPPacket(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.4.1") + dstIP := net.ParseIP("10.0.4.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + pkt := ebpftest.BuildUDPPacket(ebpftest.UDPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 53000, + DstPort: 53, + }) + + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + + assert.Equal(t, ebpftest.IPToNative("10.0.4.1"), event.SrcIp) + assert.Equal(t, ebpftest.IPToNative("10.0.4.2"), event.DstIp) + assert.Equal(t, ebpftest.PortToNetwork(53000), event.SrcPort) + assert.Equal(t, ebpftest.PortToNetwork(53), event.DstPort) + assert.Equal(t, uint8(protoUDP), event.Proto) + // UDP packets have flags=1 in the eBPF program. + assert.Equal(t, uint16(1), event.Flags) +} + +func TestFilterMapFiltering(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.5.1") + dstIP := net.ParseIP("10.0.5.2") + + // Don't populate the filter map — neither IP should match. + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 6000, + DstPort: 80, + SYN: true, + }) + + t.Run("no_match_no_event", func(t *testing.T) { + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + ebpftest.AssertNoPerfEvent(t, reader, perfReaderTimeout) + }) + + t.Run("match_after_adding_ip", func(t *testing.T) { + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event after adding IP to filter") + assert.Equal(t, ebpftest.IPToNative("10.0.5.1"), event.SrcIp) + }) +} + +func TestNonTCPUDP_NoEvent(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.6.1") + dstIP := net.ParseIP("10.0.6.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // ICMP is protocol 1 — the eBPF program only handles TCP and UDP. + pkt := ebpftest.BuildICMPPacket(srcIP, dstIP) + + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret, "should still return TC_ACT_UNSPEC") + + ebpftest.AssertNoPerfEvent(t, reader, perfReaderTimeout) +} + +func TestNonIPv4_NoEvent(t *testing.T) { + objs, reader := loadTestObjects(t) + + tests := []struct { + name string + etherType layers.EthernetType + }{ + {"ARP", layers.EthernetTypeARP}, + {"IPv6", layers.EthernetTypeIPv6}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + pkt := ebpftest.BuildNonIPPacket(tc.etherType) + + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret) + + ebpftest.AssertNoPerfEvent(t, reader, perfReaderTimeout) + }) + } +} + +func TestMalformedPackets(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.7.1") + dstIP := net.ParseIP("10.0.7.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + t.Run("runt_packet", func(t *testing.T) { + // BPF_PROG_TEST_RUN requires at least ETH_HLEN (14) bytes for TC programs. + // The kernel rejects shorter inputs with EINVAL. + pkt := ebpftest.BuildRuntPacket() + _, err := objs.EndpointIngressFilter.Run(&ebpf.RunOptions{Data: pkt}) + assert.Error(t, err, "kernel should reject packets shorter than ETH_HLEN") + }) + + t.Run("truncated_ip", func(t *testing.T) { + pkt := ebpftest.BuildTruncatedIPPacket() + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret) + ebpftest.AssertNoPerfEvent(t, reader, perfReaderTimeout) + }) + + t.Run("truncated_tcp", func(t *testing.T) { + // Note: BPF_PROG_TEST_RUN may pad sk_buff to minimum frame size, + // which means the eBPF bounds check can pass even for truncated packets. + // This test verifies the program doesn't crash on short TCP headers. + pkt := ebpftest.BuildTruncatedTCPPacket(srcIP, dstIP) + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret) + + // Drain any event that may have been emitted due to kernel padding. + reader.SetDeadline(time.Now().Add(100 * time.Millisecond)) + reader.Read() //nolint:errcheck + }) +} + +func TestReturnValue(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.8.1") + dstIP := net.ParseIP("10.0.8.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + programs := []*ebpf.Program{ + objs.EndpointIngressFilter, + objs.EndpointEgressFilter, + objs.HostIngressFilter, + objs.HostEgressFilter, + } + + // Test with various packet types (all >= ETH_HLEN to satisfy kernel). + packets := [][]byte{ + ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 8000, DstPort: 80, SYN: true, + }), + ebpftest.BuildUDPPacket(ebpftest.UDPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 8001, DstPort: 53, + }), + ebpftest.BuildNonIPPacket(layers.EthernetTypeARP), + ebpftest.BuildTruncatedIPPacket(), + } + + for _, prog := range programs { + for _, pkt := range packets { + ret := ebpftest.RunProgram(t, prog, pkt) + assert.Equal(t, uint32(tcActUnspec), ret) + + // Drain any perf event. + reader.SetDeadline(time.Now().Add(50 * time.Millisecond)) + reader.Read() //nolint:errcheck + } + } +} + +func TestPacketBytesField(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.9.1") + dstIP := net.ParseIP("10.0.9.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + payloadSizes := []int{0, 100, 1000} + + for _, payloadSize := range payloadSizes { + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 9000, + DstPort: 80, + SYN: true, + PayloadSize: payloadSize, + }) + + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + assert.Equal(t, uint32(len(pkt)), event.Bytes, "Bytes field should equal packet length (payload size: %d)", payloadSize) + } +} + +func TestConntrackMapUpdated(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.10.1") + dstIP := net.ParseIP("10.0.10.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 10000, + DstPort: 80, + SYN: true, + }) + + // First run — should create a new conntrack entry. + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + _, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event on first run") + + // Check that the conntrack map now has an entry for this flow. + lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.10.1", "10.0.10.2", 10000, 80, protoTCP) +} + +func TestConntrackIsReply(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.11.1") + dstIP := net.ParseIP("10.0.11.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // Send SYN: 10.0.11.1:20000 → 10.0.11.2:80 (new connection, forward direction). + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 20000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected perf event for SYN") + assert.False(t, event.IsReply, "SYN packet should not be a reply") + + // Send SYN-ACK: 10.0.11.2:80 → 10.0.11.1:20000 (reply direction — reversed 5-tuple). + synAckPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: dstIP, DstIP: srcIP, SrcPort: 80, DstPort: 20000, SYN: true, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synAckPkt) + event, ok = ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected perf event for SYN-ACK") + assert.True(t, event.IsReply, "SYN-ACK with reversed 5-tuple should be a reply") + + // Send another packet in forward direction: 10.0.11.1:20000 → 10.0.11.2:80. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 20000, DstPort: 80, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + event, ok = ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected perf event for ACK") + assert.False(t, event.IsReply, "forward direction ACK should not be a reply") +} + +func TestConntrackTrafficDirection(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.12.1") + dstIP := net.ParseIP("10.0.12.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // For a NEW connection, traffic_direction is derived from the observation point: + // FROM_ENDPOINT (0x00) or TO_NETWORK (0x03) → EGRESS (0x02) + // TO_ENDPOINT (0x01) or FROM_NETWORK (0x02) → INGRESS (0x01) + tests := []struct { + name string + prog *ebpf.Program + srcPort uint16 + expectedDirection uint8 + }{ + {"endpoint_ingress→egress", objs.EndpointIngressFilter, 30000, trafficDirectionEgress}, + {"endpoint_egress→ingress", objs.EndpointEgressFilter, 30001, trafficDirectionIngress}, + {"host_ingress→ingress", objs.HostIngressFilter, 30002, trafficDirectionIngress}, + {"host_egress→egress", objs.HostEgressFilter, 30003, trafficDirectionEgress}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: tc.srcPort, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, tc.prog, pkt) + + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a perf event") + assert.Equal(t, tc.expectedDirection, event.TrafficDirection, + "unexpected traffic direction for observation point") + }) + } +} + +// lookupConntrackEntry looks up a conntrack entry by 5-tuple and returns it. +func lookupConntrackEntry(t *testing.T, ctMap *ebpf.Map, srcIP, dstIP string, srcPort, dstPort uint16, proto uint8) packetparserCtEntry { + t.Helper() + ctKey := packetparserCtV4Key{ + SrcIp: ebpftest.IPToNative(srcIP), + DstIp: ebpftest.IPToNative(dstIP), + SrcPort: ebpftest.PortToNetwork(srcPort), + DstPort: ebpftest.PortToNetwork(dstPort), + Proto: proto, + } + var entry packetparserCtEntry + err := ctMap.Lookup(ctKey, &entry) + require.NoError(t, err, "conntrack entry not found for %s:%d → %s:%d proto=%d", + srcIP, srcPort, dstIP, dstPort, proto) + return entry +} + +// drainPerfEvent reads and discards one perf event if available. +func drainPerfEvent(reader *perf.Reader, timeout time.Duration) { + reader.SetDeadline(time.Now().Add(timeout)) + reader.Read() //nolint:errcheck +} + +// compileOpts controls the dynamic.h flags for a custom-compiled eBPF variant. +type compileOpts struct { + bypassFilter int + enableConntrack bool + aggregationLevel int + samplingRate int +} + +// compileAndLoadVariant compiles the packetparser eBPF program with custom +// dynamic.h settings and returns loaded objects + perf reader. +// Requires clang to be installed. +func compileAndLoadVariant(t *testing.T, opts compileOpts) (*packetparserObjects, *perf.Reader) { + t.Helper() + ebpftest.RequirePrivileged(t) + + if _, err := exec.LookPath("clang"); err != nil { + t.Skip("skipping: clang not available for eBPF compilation") + } + + // Get source directory (uses runtime.Caller to find the file path). + _, filename, _, ok := runtime.Caller(0) + require.True(t, ok, "failed to get current file path") + dir := path.Dir(filename) + + // Write custom packetparser dynamic.h, restore on cleanup. + ppDynamic := fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName) + origPP, err := os.ReadFile(ppDynamic) + require.NoError(t, err) + t.Cleanup(func() { os.WriteFile(ppDynamic, origPP, 0o644) }) //nolint:errcheck + + var st string + st += fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n", opts.bypassFilter) + if opts.enableConntrack { + st += "#define ENABLE_CONNTRACK_METRICS 1\n" + } + st += fmt.Sprintf("#define DATA_AGGREGATION_LEVEL %d\n", opts.aggregationLevel) + st += fmt.Sprintf("#define DATA_SAMPLING_RATE %d\n", opts.samplingRate) + require.NoError(t, os.WriteFile(ppDynamic, []byte(st), 0o644)) + + // Write conntrack dynamic.h if conntrack metrics enabled. + ctDynamic := fmt.Sprintf("%s/../conntrack/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName) + origCT, err := os.ReadFile(ctDynamic) + require.NoError(t, err) + t.Cleanup(func() { os.WriteFile(ctDynamic, origCT, 0o644) }) //nolint:errcheck + + if opts.enableConntrack { + require.NoError(t, os.WriteFile(ctDynamic, []byte("#define ENABLE_CONNTRACK_METRICS 1\n"), 0o644)) + } + + // Compile the eBPF program. + bpfSourceFile := fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, bpfSourceFileName) + outputFile := fmt.Sprintf("%s/packetparser_test.o", t.TempDir()) + + arch := runtime.GOARCH + targetArch := "-D__TARGET_ARCH_x86" + if arch == "arm64" { + targetArch = "-D__TARGET_ARCH_arm64" + } + + log.SetupZapLogger(log.GetDefaultLogOpts()) //nolint:errcheck + err = loader.CompileEbpf(context.Background(), + "-target", "bpf", "-Wall", targetArch, "-g", "-O2", + "-c", bpfSourceFile, "-o", outputFile, + fmt.Sprintf("-I%s/../lib/_%s", dir, arch), + fmt.Sprintf("-I%s/../lib/common/libbpf/_src", dir), + fmt.Sprintf("-I%s/../lib/common/libbpf/_include/linux", dir), + fmt.Sprintf("-I%s/../lib/common/libbpf/_include/uapi/linux", dir), + fmt.Sprintf("-I%s/../lib/common/libbpf/_include/asm", dir), + fmt.Sprintf("-I%s/../filter/_cprog/", dir), + fmt.Sprintf("-I%s/../conntrack/_cprog/", dir), + ) + require.NoError(t, err, "failed to compile eBPF program") + + // Load the compiled object. + spec, err := ebpf.LoadCollectionSpec(outputFile) + require.NoError(t, err) + ebpftest.RemoveMapPinning(spec) + + var objs packetparserObjects + err = spec.LoadAndAssign(&objs, nil) + require.NoError(t, err) + t.Cleanup(func() { objs.Close() }) + + reader, err := perf.NewReader(objs.RetinaPacketparserEvents, os.Getpagesize()*4) + require.NoError(t, err) + t.Cleanup(func() { reader.Close() }) + + return &objs, reader +} + +func TestConntrackMetricsEnabled(t *testing.T) { + objs, reader := compileAndLoadVariant(t, compileOpts{ + bypassFilter: 1, // skip filter for simplicity + enableConntrack: true, + aggregationLevel: 0, // LOW — always emit + samplingRate: 1, + }) + + srcIP := net.ParseIP("10.0.13.1") + dstIP := net.ParseIP("10.0.13.2") + + // Send SYN (creates conntrack entry). + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 40000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + _, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok) + + // Send a second packet in the same direction (existing forward connection). + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 40000, DstPort: 80, ACK: true, + PayloadSize: 100, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok) + + // With ENABLE_CONNTRACK_METRICS, the conntrack_metadata should be populated. + // After 2 packets in TX direction, packets_tx_count should be >= 1. + assert.True(t, event.ConntrackMetadata.PacketsTxCount >= 1, + "expected packets_tx_count >= 1, got %d", event.ConntrackMetadata.PacketsTxCount) + assert.True(t, event.ConntrackMetadata.BytesTxCount > 0, + "expected bytes_tx_count > 0, got %d", event.ConntrackMetadata.BytesTxCount) + + // Send a reply packet (reverse direction). + replyPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: dstIP, DstIP: srcIP, SrcPort: 80, DstPort: 40000, ACK: true, + PayloadSize: 200, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, replyPkt) + event, ok = ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok) + + assert.True(t, event.IsReply, "reverse packet should be is_reply") + assert.True(t, event.ConntrackMetadata.PacketsRxCount >= 1, + "expected packets_rx_count >= 1, got %d", event.ConntrackMetadata.PacketsRxCount) + assert.True(t, event.ConntrackMetadata.BytesRxCount > 0, + "expected bytes_rx_count > 0, got %d", event.ConntrackMetadata.BytesRxCount) +} + +func TestHighAggregationLevel(t *testing.T) { + objs, reader := compileAndLoadVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: false, + aggregationLevel: 1, // HIGH — only emit when report.report is true + samplingRate: 1, // sample everything + }) + + srcIP := net.ParseIP("10.0.14.1") + dstIP := net.ParseIP("10.0.14.2") + + // First SYN packet should be reported (new connection). + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 50000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "first SYN should be reported at HIGH aggregation") + assert.Equal(t, uint8(protoTCP), event.Proto) + + // Send several identical ACK packets. At HIGH aggregation, the conntrack + // logic suppresses repeated reports until new flags appear or a timeout. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 50000, DstPort: 80, ACK: true, + }) + emittedCount := 0 + for i := 0; i < 5; i++ { + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + _, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, 100*time.Millisecond) + if ok { + emittedCount++ + } + } + // At HIGH aggregation, not all 5 identical ACK packets should be reported. + // The first ACK introduces a new flag (ACK vs SYN), so it should be reported. + // Subsequent identical ACKs may be suppressed. + t.Logf("HIGH aggregation: %d/5 ACK packets emitted events", emittedCount) + assert.True(t, emittedCount < 5, + "HIGH aggregation should suppress some repeated packets, but all %d were emitted", emittedCount) +} + +func TestHighAggregationPreviouslyObserved(t *testing.T) { + objs, reader := compileAndLoadVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: false, + aggregationLevel: 1, // HIGH + samplingRate: 1, + }) + + srcIP := net.ParseIP("10.0.15.1") + dstIP := net.ParseIP("10.0.15.2") + + // Send SYN to create the connection. + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 60000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + _, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok) + + // Send multiple packets to accumulate stats, then send a packet with a new + // flag to trigger a report that includes previously_observed_* fields. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 60000, DstPort: 80, ACK: true, + PayloadSize: 50, + }) + for i := 0; i < 3; i++ { + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + // Drain any events. + reader.SetDeadline(time.Now().Add(50 * time.Millisecond)) + reader.Read() //nolint:errcheck + } + + // Send FIN to introduce a new flag — this should trigger a report. + finPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 60000, DstPort: 80, FIN: true, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, finPkt) + event, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "FIN should trigger a report due to new flag") + + // At HIGH aggregation, the report should include accumulated stats. + // previously_observed_packets counts packets seen since last report. + t.Logf("previously_observed_packets=%d, previously_observed_bytes=%d", + event.PreviouslyObservedPackets, event.PreviouslyObservedBytes) + assert.True(t, event.PreviouslyObservedPackets > 0, + "expected previously_observed_packets > 0 at HIGH aggregation") +} + +// ============================================================================= +// Conntrack map-state verification tests +// ============================================================================= + +func TestConntrackEntryCreation(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.20.1") + dstIP := net.ParseIP("10.0.20.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 20000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + _, ok := ebpftest.ReadPerfEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok) + + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.20.1", "10.0.20.2", 20000, 80, protoTCP) + + // FlagsSeenTxDir: SYN = 0x02. + assert.Equal(t, uint8(0x02), entry.FlagsSeenTxDir, "should have SYN in TX flags") + // No reply yet. + assert.Equal(t, uint8(0x00), entry.FlagsSeenRxDir, "RX flags should be empty") + // Direction is known because we saw SYN. + assert.False(t, entry.IsDirectionUnknown, "direction should be known for SYN") + // EndpointIngressFilter = FROM_ENDPOINT → EGRESS. + assert.Equal(t, uint8(trafficDirectionEgress), entry.TrafficDirection) + // Eviction time must be set. + assert.NotZero(t, entry.EvictionTime, "eviction time should be non-zero") + // Sampled + reported → "since last report" counters are 0. + assert.Equal(t, uint32(0), entry.PacketsSeenSinceLastReportTxDir) + assert.Equal(t, uint32(0), entry.BytesSeenSinceLastReportTxDir) +} + +func TestConntrackFlagAccumulation(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.21.1") + dstIP := net.ParseIP("10.0.21.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // Step 1: SYN → flags_seen_tx_dir = SYN (0x02). + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 21000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.21.1", "10.0.21.2", 21000, 80, protoTCP) + assert.Equal(t, uint8(0x02), entry.FlagsSeenTxDir, "after SYN") + + // Step 2: ACK → flags_seen_tx_dir = SYN|ACK (0x12). + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 21000, DstPort: 80, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.21.1", "10.0.21.2", 21000, 80, protoTCP) + assert.Equal(t, uint8(0x12), entry.FlagsSeenTxDir, "after ACK: should be SYN|ACK") + + // Step 3: PSH+ACK → flags_seen_tx_dir = SYN|PSH|ACK (0x1A). + pshPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 21000, DstPort: 80, PSH: true, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pshPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.21.1", "10.0.21.2", 21000, 80, protoTCP) + assert.Equal(t, uint8(0x1A), entry.FlagsSeenTxDir, "after PSH+ACK: should be SYN|PSH|ACK") +} + +func TestConntrackReplyUpdatesEntry(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.22.1") + dstIP := net.ParseIP("10.0.22.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // Forward SYN: 10.0.22.1:22000 → 10.0.22.2:80. + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 22000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.22.1", "10.0.22.2", 22000, 80, protoTCP) + assert.Equal(t, uint8(0x02), entry.FlagsSeenTxDir, "initial TX: SYN") + assert.Equal(t, uint8(0x00), entry.FlagsSeenRxDir, "initial RX: empty") + + // Reply SYN-ACK: 10.0.22.2:80 → 10.0.22.1:22000 (reverse 5-tuple). + // Conntrack finds the entry via reverse key lookup and updates RX fields. + synAckPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: dstIP, DstIP: srcIP, SrcPort: 80, DstPort: 22000, SYN: true, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synAckPkt) + drainPerfEvent(reader, perfReaderTimeout) + + // Entry is still under the forward (initiator's) key. + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.22.1", "10.0.22.2", 22000, 80, protoTCP) + // TX unchanged. + assert.Equal(t, uint8(0x02), entry.FlagsSeenTxDir, "TX should still be SYN") + // RX updated with SYN|ACK. + assert.Equal(t, uint8(0x12), entry.FlagsSeenRxDir, "RX should be SYN|ACK after reply") + + // Forward ACK: 10.0.22.1:22000 → 10.0.22.2:80. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 22000, DstPort: 80, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.22.1", "10.0.22.2", 22000, 80, protoTCP) + // TX accumulates ACK. + assert.Equal(t, uint8(0x12), entry.FlagsSeenTxDir, "TX should be SYN|ACK after handshake") + // RX unchanged. + assert.Equal(t, uint8(0x12), entry.FlagsSeenRxDir, "RX still SYN|ACK") +} + +func TestConntrackDirectionUnknown(t *testing.T) { + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.23.1") + dstIP := net.ParseIP("10.0.23.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // Send PSH+ACK as the first packet (simulates missed SYN — ongoing connection). + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 23000, DstPort: 80, PSH: true, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + drainPerfEvent(reader, perfReaderTimeout) + + // ACK flag is set → _ct_handle_tcp_connection treats as reply → stored under reverse key. + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.23.2", "10.0.23.1", 80, 23000, protoTCP) + + assert.True(t, entry.IsDirectionUnknown, + "IsDirectionUnknown should be true for non-SYN first packet") + // Flags stored in RX direction (treated as reply due to ACK). + assert.Equal(t, uint8(0x18), entry.FlagsSeenRxDir, "RX should have PSH|ACK (0x18)") + assert.Equal(t, uint8(0x00), entry.FlagsSeenTxDir, "TX should be empty") +} + +func TestConntrackSinceLastReportAccumulation(t *testing.T) { + // At HIGH aggregation, packets that don't introduce new flags are suppressed. + // Their bytes and packet counts accumulate in "since last report" counters. + objs, reader := compileAndLoadVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: false, + aggregationLevel: 1, // HIGH + samplingRate: 1, + }) + + srcIP := net.ParseIP("10.0.24.1") + dstIP := net.ParseIP("10.0.24.2") + + // SYN creates the entry (reported — SYN is a should_report flag). + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 24000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + drainPerfEvent(reader, perfReaderTimeout) + + // First ACK introduces new flag → reported → counters reset. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 24000, DstPort: 80, ACK: true, + PayloadSize: 100, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, perfReaderTimeout) + + // Subsequent identical ACKs: no new flags, within 30s → NOT reported → counters accumulate. + for i := 0; i < 3; i++ { + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, 100*time.Millisecond) + } + + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.24.1", "10.0.24.2", 24000, 80, protoTCP) + + // 3 non-reported ACK packets should have accumulated. + assert.True(t, entry.PacketsSeenSinceLastReportTxDir >= 3, + "expected PacketsSeenSinceLastReportTxDir >= 3, got %d", + entry.PacketsSeenSinceLastReportTxDir) + assert.True(t, entry.BytesSeenSinceLastReportTxDir > 0, + "expected BytesSeenSinceLastReportTxDir > 0, got %d", + entry.BytesSeenSinceLastReportTxDir) + + // FlagsSeenSinceLastReportTxDir should have ACK counts. + assert.True(t, entry.FlagsSeenSinceLastReportTxDir.Ack >= 3, + "expected ACK flag count >= 3 since last report, got %d", + entry.FlagsSeenSinceLastReportTxDir.Ack) +} + +func TestConntrackCounterResetOnReport(t *testing.T) { + // Verify that "since last report" counters reset to 0 when a report is emitted. + objs, reader := compileAndLoadVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: false, + aggregationLevel: 1, // HIGH + samplingRate: 1, + }) + + srcIP := net.ParseIP("10.0.25.1") + dstIP := net.ParseIP("10.0.25.2") + + // SYN → reported. + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 25000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + drainPerfEvent(reader, perfReaderTimeout) + + // First ACK → reported (new flag), counters reset. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 25000, DstPort: 80, ACK: true, + PayloadSize: 100, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, perfReaderTimeout) + + // Send 3 more ACKs to accumulate counters. + for i := 0; i < 3; i++ { + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, 100*time.Millisecond) + } + + // Verify counters accumulated. + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.25.1", "10.0.25.2", 25000, 80, protoTCP) + require.True(t, entry.PacketsSeenSinceLastReportTxDir >= 3, + "precondition: counters should be accumulated before FIN") + + // Send FIN+ACK → FIN is a should_report flag → report triggered → counters reset. + finPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 25000, DstPort: 80, FIN: true, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, finPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.25.1", "10.0.25.2", 25000, 80, protoTCP) + assert.Equal(t, uint32(0), entry.PacketsSeenSinceLastReportTxDir, + "counters should be 0 after FIN report") + assert.Equal(t, uint32(0), entry.BytesSeenSinceLastReportTxDir, + "byte counters should be 0 after FIN report") + assert.Equal(t, uint32(0), entry.FlagsSeenSinceLastReportTxDir.Ack, + "flag counts should be 0 after FIN report") +} + +func TestConntrackMetadataCountersInMap(t *testing.T) { + // With ENABLE_CONNTRACK_METRICS, the ConntrackMetadata lifetime counters + // are updated on every packet and never reset. + objs, reader := compileAndLoadVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: true, + aggregationLevel: 0, // LOW — always emit + samplingRate: 1, + }) + + srcIP := net.ParseIP("10.0.26.1") + dstIP := net.ParseIP("10.0.26.2") + + // Forward SYN. + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 26000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.26.1", "10.0.26.2", 26000, 80, protoTCP) + // _ct_create_new_tcp_connection sets packets_tx_count=1. + assert.Equal(t, uint32(1), entry.ConntrackMetadata.PacketsTxCount, "initial TX packets") + assert.True(t, entry.ConntrackMetadata.BytesTxCount > 0, "initial TX bytes > 0") + assert.Equal(t, uint32(0), entry.ConntrackMetadata.PacketsRxCount, "initial RX packets") + assert.Equal(t, uint64(0), entry.ConntrackMetadata.BytesRxCount, "initial RX bytes") + + // Send 2 more forward packets. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 26000, DstPort: 80, ACK: true, + PayloadSize: 200, + }) + for i := 0; i < 2; i++ { + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, perfReaderTimeout) + } + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.26.1", "10.0.26.2", 26000, 80, protoTCP) + // 1 SYN + 2 ACK = 3 TX packets. + assert.Equal(t, uint32(3), entry.ConntrackMetadata.PacketsTxCount, "3 TX packets total") + + // Send a reply packet. + replyPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: dstIP, DstIP: srcIP, SrcPort: 80, DstPort: 26000, ACK: true, + PayloadSize: 300, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, replyPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.26.1", "10.0.26.2", 26000, 80, protoTCP) + // TX unchanged. + assert.Equal(t, uint32(3), entry.ConntrackMetadata.PacketsTxCount, "TX still 3") + // RX incremented. + assert.Equal(t, uint32(1), entry.ConntrackMetadata.PacketsRxCount, "1 RX packet") + assert.True(t, entry.ConntrackMetadata.BytesRxCount > 0, "RX bytes > 0") +} + +func TestConntrackEvictionTimeExtended(t *testing.T) { + // Verify that EvictionTime is extended on subsequent packets. + objs, reader := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.27.1") + dstIP := net.ParseIP("10.0.27.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + // SYN: eviction_time = now + CT_SYN_TIMEOUT (60s). + synPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 27000, DstPort: 80, SYN: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, synPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry := lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.27.1", "10.0.27.2", 27000, 80, protoTCP) + synEviction := entry.EvictionTime + assert.NotZero(t, synEviction) + + // ACK: eviction_time = now + CT_CONNECTION_LIFETIME_TCP (360s) — should be larger. + ackPkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: 27000, DstPort: 80, ACK: true, + }) + ebpftest.RunProgram(t, objs.EndpointIngressFilter, ackPkt) + drainPerfEvent(reader, perfReaderTimeout) + + entry = lookupConntrackEntry(t, objs.RetinaConntrack, + "10.0.27.1", "10.0.27.2", 27000, 80, protoTCP) + assert.True(t, entry.EvictionTime > synEviction, + "eviction time should increase after ACK (60s SYN timeout → 360s established), got %d → %d", + synEviction, entry.EvictionTime) +} From aaafa9aad09888e62379b532084df85dc7422d20 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 2 Apr 2026 10:30:14 -0400 Subject: [PATCH 283/448] feat(ci): add generated code and BPF stub freshness check (#2146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Currently there is no CI check to verify that generated code (mockgen, bpf2go, controller-gen) matches what is committed. Stale mocks or missing generated files can slip through review and cause build failures that only surface later in the test-image build. This PR adds a `Check Generated Code` workflow that runs `go generate` on native amd64 and arm64 runners, then verifies three things: 1. **Non-empty `.o` stubs** (before generate): Tracked `.o` files must be 0 bytes in the committed tree — real BPF objects are built at image build time, not checked in 2. **Stale generated `.go` files** (after generate): Diffs generated output against committed code 3. **Missing generated files** (after generate): Catches new files from `go generate` that weren't committed Errors appear as GitHub annotations on the PR checks tab with actionable fix instructions. ## Related Issue N/A — discovered during the Cilium v1.19 upgrade (#1788) when a stale packetparser mock went undetected. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Validated by pushing stub commits to trigger each failure mode. ### Non-empty `.o` file ([run 23673904628](https://github.com/microsoft/retina/actions/runs/23673904628)) ``` ============================================================ ERROR: The following .o files must be empty stubs (0 bytes). pkg/plugin/packetparser/packetparser_bpfel_x86.o (10 bytes) Run 'make empty-bpf-objects' to truncate them, then commit. ============================================================ ``` Annotation: `Non-empty .o files committed. Run 'make empty-bpf-objects' and commit the result.` ### Stale generated code ([run 23672788052](https://github.com/microsoft/retina/actions/runs/23672788052)) ``` ============================================================ ERROR: Generated code is out of date. The following files differ after running 'make generate': pkg/plugin/packetparser/mocks/mock_types_linux.go Please run 'make generate' locally and commit the changes. ============================================================ ============================================================ ERROR: New generated files are not committed. pkg/hubble/common/mocks/mock_types.go pkg/plugin/dropreason/mocks/mock_types.go Please run 'make generate' locally and commit the new files. ============================================================ ``` ## Additional Notes The workflow installs `clang`, `llvm`, `lld`, and `libbpf-dev` on the runner to support BPF code generation. Runs on `pull_request` only with a 15-minute timeout per arch. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- .github/workflows/generate-check.yaml | 113 ++++++++++++++++++++++++++ pkg/hubble/common/decoder_linux.go | 2 - 2 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/generate-check.yaml diff --git a/.github/workflows/generate-check.yaml b/.github/workflows/generate-check.yaml new file mode 100644 index 0000000000..a80585f4f6 --- /dev/null +++ b/.github/workflows/generate-check.yaml @@ -0,0 +1,113 @@ +name: Check Generated Code +on: + pull_request: + branches: [main] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + generate-check: + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + name: Generate (${{ matrix.arch }}) + runs-on: ${{ matrix.runner }} + timeout-minutes: 15 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + with: + go-version-file: go.mod + + - name: Check that committed .o files are empty stubs + run: | + RED='\033[0;31m' + YELLOW='\033[1;33m' + CYAN='\033[0;36m' + NC='\033[0m' + # Tracked .o files must be empty (0 bytes) in the committed tree. + # They exist so Go source with bpf2go references compiles without + # running go generate. Real BPF objects are built at image build time. + # This check runs BEFORE generate since generate populates them. + non_empty=$(git ls-files '*.o' | while read -r f; do + size=$(git cat-file -s "HEAD:$f" 2>/dev/null || echo 0) + if [ "$size" -gt 0 ]; then echo "$f ($size bytes)"; fi + done || true) + if [ -n "$non_empty" ]; then + echo "" + echo -e "${RED}============================================================${NC}" + echo -e "${RED}ERROR: The following .o files must be empty stubs (0 bytes).${NC}" + echo "" + echo -e "${YELLOW}${non_empty}${NC}" + echo "" + echo -e "${CYAN}Run 'make empty-bpf-objects' to truncate them, then commit.${NC}" + echo -e "${RED}============================================================${NC}" + echo "::error::Non-empty .o files committed. Run 'make empty-bpf-objects' and commit the result." + exit 1 + fi + + - name: Install BPF build dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y --no-install-recommends clang llvm lld libbpf-dev linux-headers-$(uname -r) + sudo apt-get install -y --no-install-recommends linux-tools-$(uname -r) linux-tools-common || true + + - name: Run make generate for ${{ matrix.arch }} + run: | + # Generate BPF objects and Go bindings for this runner's native arch only, + # then run the remaining (non-BPF) generators. + GOARCH=${{ matrix.arch }} go generate ./pkg/plugin/... + go generate ./... + + - name: Check for uncommitted changes + run: | + RED='\033[0;31m' + YELLOW='\033[1;33m' + CYAN='\033[0;36m' + NC='\033[0m' + failed=0 + + # 1. Check generated .go files match committed code. + # Ignore .o files — they are empty stubs in the repo and get + # populated with real BPF objects during generate. + if ! git diff --quiet -- ':!*.o'; then + echo "" + echo -e "${RED}============================================================${NC}" + echo -e "${RED}ERROR: Generated code is out of date.${NC}" + echo "" + echo -e "${YELLOW}The following files differ after running 'make generate':${NC}" + git diff --name-only -- ':!*.o' + echo "" + echo -e "${CYAN}Please run 'make generate' locally and commit the changes.${NC}" + echo -e "${RED}============================================================${NC}" + echo "::error::Generated code is out of date. Run 'make generate' locally and commit the changes." + failed=1 + fi + + # 2. Check for new generated files that weren't committed. + untracked=$(git ls-files --others --exclude-standard -- '*.go' | head -20) + if [ -n "$untracked" ]; then + echo "" + echo -e "${RED}============================================================${NC}" + echo -e "${RED}ERROR: New generated files are not committed.${NC}" + echo "" + echo -e "${YELLOW}${untracked}${NC}" + echo "" + echo -e "${CYAN}Please run 'make generate' locally and commit the new files.${NC}" + echo -e "${RED}============================================================${NC}" + echo "::error::New generated files are not committed. Run 'make generate' locally and commit the new files." + failed=1 + fi + + exit $failed diff --git a/pkg/hubble/common/decoder_linux.go b/pkg/hubble/common/decoder_linux.go index 267d4758ee..d5eed5989d 100644 --- a/pkg/hubble/common/decoder_linux.go +++ b/pkg/hubble/common/decoder_linux.go @@ -10,8 +10,6 @@ import ( "github.com/cilium/cilium/pkg/labels" ) -//go:generate go run github.com/golang/mock/mockgen@v1.6.0 -source decoder.go -destination=mocks/mock_types.go -package=mocks - type EpDecoder interface { Decode(ip netip.Addr) *flow.Endpoint IsEndpointOnLocalHost(ip string) bool From 5298695ea6ff745dea9b3e9b10bd9991cdf9f178 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:30:36 +0000 Subject: [PATCH 284/448] deps: Bump actions/setup-go from 6.2.0 to 6.4.0 (#2155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.2.0 to 6.4.0.
Release notes

Sourced from actions/setup-go's releases.

v6.4.0

What's Changed

Enhancement

Dependency update

Documentation update

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.4.0

v6.3.0

What's Changed

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.3.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=6.2.0&new-version=6.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test-ebpf.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-ebpf.yaml b/.github/workflows/test-ebpf.yaml index 4503f4aa0d..234e78ccf3 100644 --- a/.github/workflows/test-ebpf.yaml +++ b/.github/workflows/test-ebpf.yaml @@ -31,7 +31,7 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod From 504f9ad5b602554757d939fd179e01f59460532e Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 2 Apr 2026 16:38:33 +0100 Subject: [PATCH 285/448] fix: namespace exclude filtering (#2118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fix: Namespace Exclude Filtering in MetricConfiguration CRD ## Problem The namespace exclude filtering feature in the MetricConfiguration CRD is completely non-functional due to two separate bugs: 1. **`appendExcludeList()` is empty** — The function body contains only a TODO comment and never populates the exclude map or manages the filtermanager. Setting `spec.namespaces.exclude` has no effect. 2. **`updateNamespaceLists()` has logic errors** — Sequential `if` statements instead of `if/else` cause both include and exclude lists to be reset when only one should be active. This means any cluster using `spec.namespaces.exclude` in a MetricsConfiguration CRD gets no namespace filtering at all — either no IPs are added to the filtermap (no metrics collected) or all IPs are added without filtering (eBPF map exhaustion). ## Fix **Three changes in `pkg/module/metrics/metrics_module.go`:** 1. **Implement `appendExcludeList()`** — Mirrors the existing `appendIncludeList()` pattern: diffs old vs new exclude set, removes IPs for newly-excluded namespaces from filtermanager, adds IPs for newly-un-excluded namespaces. On initial activation of exclude mode, uses `GetAllNamespaces()` to add IPs for all non-excluded namespaces. 2. **Fix `updateNamespaceLists()` control flow** — Replaced four sequential `if` blocks with a proper `if/else if/else` chain. Added `return` after the both-set error case to prevent state mutation. Clears the opposite mode before activating the new one to avoid filtermanager entry conflicts. 3. **Add doc comment to `nsOfInterest()`** — Clarifies that when no namespace filters are configured, no namespace is considered of interest by default — pods must be individually annotated or already in the filtermap. **One change in `pkg/controllers/cache/`:** 4. **Add `GetAllNamespaces()` to `CacheInterface`** — Returns all unique namespaces that have at least one endpoint in the cache. Needed by `appendExcludeList()` to compute the set of non-excluded namespaces when exclude mode activates. Iterates `epMap` since `nsMap` is unused. ## Tests Unit tests added covering: - `TestNsOfInterest` — Verifies correct behavior for include-only, exclude-only, and no-filter cases (6 subcases) - `TestAppendExcludeList` — Mirrors existing `TestAppendIncludeList`: add, change, remove exclude namespaces (5 subcases) - `TestUpdateNamespaceListsExclude` — Exclude-only spec populates `excludedNamespaces` and clears `includedNamespaces` - `TestPodCallBackExclude` — End-to-end: pod in non-excluded ns is tracked, pod in excluded ns is not - `TestGetAllNamespaces` — Cache returns unique namespace list from endpoint map All existing tests pass (no regressions). ### Manual test #### Scenario 1 — Namespace exclude filtering (MetricsConfiguration CRD mode) Test: ```bash # helm install with: enableAnnotations=false, enablePodLevel=true, operator.enabled=true kubectl create namespace test-include kubectl create namespace test-exclude Apply MetricsConfiguration CRD with namespaces.exclude: [test-exclude] # → Verify: CRD status is "Accepted" kubectl run pod-include -n test-include --image=nginx # → Verify: "Adding pod IP to ADD dirty pods cache" with test-include/pod-include in retina logs kubectl run pod-exclude -n test-exclude --image=nginx # → Verify: NO "Adding pod IP to ADD dirty pods cache" for test-exclude/pod-exclude kubectl delete pod pod-include -n test-include # → Verify: "Adding pod IP to DELETE dirty pods cache" with test-include/pod-include ``` Logs: ```bash === ADD phase (non-excluded namespace) === ts=2026-03-16T15:38:22.790Z level=info caller=metrics/metrics_module.go:529 msg="Adding pod IP to ADD dirty pods cache" pod name=test-include/pod-include === ADD phase (excluded namespace) === (no matching logs — correct if excluded) === DELETE phase === ts=2026-03-16T15:39:03.955Z level=info caller=metrics/metrics_module.go:532 msg="Adding pod IP to DELETE dirty pods cache" pod name=test-include/pod-include ``` Scenario 2 — Switch from exclude to include Test: ```bash Update MetricsConfiguration CRD from namespaces.exclude: [test-exclude] to namespaces.include: [test-include] # → Verify: "Including namespaces|Appending namespaces|newly excluded|newly un-excluded" log ``` Logs: ```bash ts=2026-03-16T15:39:22.959Z level=info caller=metrics/metrics_module.go:184 msg="Including namespaces" namespaces=test-include ts=2026-03-16T15:39:22.959Z level=info caller=metrics/metrics_module.go:413 msg="Appending namespaces to exclude list" namespaces= ts=2026-03-16T15:39:22.959Z level=info caller=metrics/metrics_module.go:439 msg="Namespaces newly excluded" namespaces= ts=2026-03-16T15:39:22.959Z level=info caller=metrics/metrics_module.go:440 msg="Namespaces newly un-excluded" namespaces=test-exclude ts=2026-03-16T15:39:22.960Z level=info caller=metrics/metrics_module.go:348 msg="Appending namespaces to include list" namespaces=test-include ``` ## Related Issue Fixes microsoft/retina#2085 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos Co-authored-by: Iti Agrawal --- pkg/controllers/cache/cache.go | 16 ++ pkg/controllers/cache/cache_test.go | 30 +++ pkg/controllers/cache/mock_cacheinterface.go | 14 + pkg/controllers/cache/types.go | 2 + pkg/module/metrics/metrics_module.go | 94 +++++-- .../metrics/metrics_module_linux_test.go | 254 ++++++++++++++++++ 6 files changed, 392 insertions(+), 18 deletions(-) diff --git a/pkg/controllers/cache/cache.go b/pkg/controllers/cache/cache.go index 362565c4f4..431269597b 100644 --- a/pkg/controllers/cache/cache.go +++ b/pkg/controllers/cache/cache.go @@ -168,6 +168,22 @@ func (c *Cache) GetObjByIP(ip string) interface{} { return nil } +func (c *Cache) GetAllNamespaces() []string { + c.RLock() + defer c.RUnlock() + + unique := make(map[string]struct{}) + for _, ep := range c.epMap { + unique[ep.Namespace()] = struct{}{} + } + + namespaces := make([]string, 0, len(unique)) + for ns := range unique { + namespaces = append(namespaces, ns) + } + return namespaces +} + func (c *Cache) GetIPsByNamespace(ns string) []net.IP { c.RLock() defer c.RUnlock() diff --git a/pkg/controllers/cache/cache_test.go b/pkg/controllers/cache/cache_test.go index 11beee52c6..ee5e3c42de 100644 --- a/pkg/controllers/cache/cache_test.go +++ b/pkg/controllers/cache/cache_test.go @@ -11,6 +11,7 @@ import ( "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/pubsub" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" gomock "go.uber.org/mock/gomock" ) @@ -381,3 +382,32 @@ func TestCachingNamespace(t *testing.T) { namespaces = c.GetAnnotatedNamespaces() assert.Equal(t, 0, len(namespaces)) } + +func TestGetAllNamespaces(t *testing.T) { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + p := pubsub.NewMockPubSubInterface(ctrl) + p.EXPECT().Subscribe(common.PubSubAPIServer, gomock.Any()).Times(1) + p.EXPECT().Publish(gomock.Any(), gomock.Any()).AnyTimes() + c := New(p) + + // Empty cache should return empty list + namespaces := c.GetAllNamespaces() + assert.Empty(t, namespaces) + + // Add endpoints in different namespaces + ep1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 1)}) + ep2 := common.NewRetinaEndpoint("pod2", "ns2", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 2)}) + ep3 := common.NewRetinaEndpoint("pod3", "ns1", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 3)}) + err := c.UpdateRetinaEndpoint(ep1) + require.NoError(t, err) + err = c.UpdateRetinaEndpoint(ep2) + require.NoError(t, err) + err = c.UpdateRetinaEndpoint(ep3) + require.NoError(t, err) + + namespaces = c.GetAllNamespaces() + assert.Len(t, namespaces, 2) + assert.ElementsMatch(t, []string{"ns1", "ns2"}, namespaces) +} diff --git a/pkg/controllers/cache/mock_cacheinterface.go b/pkg/controllers/cache/mock_cacheinterface.go index dd907f7927..4376a1c376 100644 --- a/pkg/controllers/cache/mock_cacheinterface.go +++ b/pkg/controllers/cache/mock_cacheinterface.go @@ -112,6 +112,20 @@ func (mr *MockCacheInterfaceMockRecorder) DeleteRetinaSvc(arg0 any) *gomock.Call return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRetinaSvc", reflect.TypeOf((*MockCacheInterface)(nil).DeleteRetinaSvc), arg0) } +// GetAllNamespaces mocks base method. +func (m *MockCacheInterface) GetAllNamespaces() []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllNamespaces") + ret0, _ := ret[0].([]string) + return ret0 +} + +// GetAllNamespaces indicates an expected call of GetAllNamespaces. +func (mr *MockCacheInterfaceMockRecorder) GetAllNamespaces() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllNamespaces", reflect.TypeOf((*MockCacheInterface)(nil).GetAllNamespaces)) +} + // GetAnnotatedNamespaces mocks base method. func (m *MockCacheInterface) GetAnnotatedNamespaces() []string { m.ctrl.T.Helper() diff --git a/pkg/controllers/cache/types.go b/pkg/controllers/cache/types.go index a37cc9f18a..22db7072ad 100644 --- a/pkg/controllers/cache/types.go +++ b/pkg/controllers/cache/types.go @@ -20,6 +20,8 @@ type CacheInterface interface { GetObjByIP(ip string) interface{} // GetIPsByNamespace returns the net.IPs for a given namespace. GetIPsByNamespace(ns string) []net.IP + // GetAllNamespaces returns all unique namespaces that have at least one endpoint in the cache. + GetAllNamespaces() []string // GetAnnotatedNamespaces returns list of namespaces that are annotated with retina to observe. GetAnnotatedNamespaces() []string diff --git a/pkg/module/metrics/metrics_module.go b/pkg/module/metrics/metrics_module.go index 617ce74475..78b771efe0 100644 --- a/pkg/module/metrics/metrics_module.go +++ b/pkg/module/metrics/metrics_module.go @@ -177,28 +177,20 @@ func (m *Module) Reconcile(spec *api.MetricsSpec) error { func (m *Module) updateNamespaceLists(spec *api.MetricsSpec) { if len(spec.Namespaces.Include) > 0 && len(spec.Namespaces.Exclude) > 0 { m.l.Error("Both included and excluded namespaces are specified. Cannot reconcile.") - } - - if len(spec.Namespaces.Include) == 0 { - m.appendIncludeList([]string{}) - m.appendExcludeList([]string{}) - } - - if len(spec.Namespaces.Exclude) == 0 { - m.appendIncludeList([]string{}) - m.appendExcludeList([]string{}) + return } if len(spec.Namespaces.Include) > 0 { m.l.Info("Including namespaces", zap.Strings("namespaces", spec.Namespaces.Include)) - m.appendIncludeList(spec.Namespaces.Include) m.appendExcludeList([]string{}) - } - - if len(spec.Namespaces.Exclude) > 0 { + m.appendIncludeList(spec.Namespaces.Include) + } else if len(spec.Namespaces.Exclude) > 0 { m.l.Info("Excluding namespaces", zap.Strings("namespaces", spec.Namespaces.Exclude)) + m.appendIncludeList([]string{}) m.appendExcludeList(spec.Namespaces.Exclude) + } else { m.appendIncludeList([]string{}) + m.appendExcludeList([]string{}) } } @@ -418,8 +410,72 @@ func (m *Module) appendExcludeList(ns []string) { m.excludedNamespaces = make(map[string]struct{}) } - // TODO here we will need to check for IP which - // needs to be added to filter manager and which needs to be removed + m.l.Info("Appending namespaces to exclude list", zap.Strings("namespaces", ns)) + + tempNewNs := make(map[string]struct{}) + for _, n := range ns { + tempNewNs[n] = struct{}{} + } + + m.l.Info("Current excluded namespaces", zap.Any("namespaces", m.excludedNamespaces)) + newlyExcluded, newlyUnexcluded := make([]string, 0), make([]string, 0) + + // Namespaces that are in the new list but not in the old list + for _, n := range ns { + if _, ok := m.excludedNamespaces[n]; !ok { + newlyExcluded = append(newlyExcluded, n) + } + } + + // Namespaces that were in the old list but not in the new list + for n := range m.excludedNamespaces { + if _, ok := tempNewNs[n]; !ok { + newlyUnexcluded = append(newlyUnexcluded, n) + } + } + + m.excludedNamespaces = tempNewNs + + m.l.Info("Namespaces newly excluded", zap.Strings("namespaces", newlyExcluded)) + m.l.Info("Namespaces newly un-excluded", zap.Strings("namespaces", newlyUnexcluded)) + + // For newly excluded namespaces: remove their IPs from filtermanager + for _, n := range newlyExcluded { + ips := m.daemonCache.GetIPsByNamespace(n) + m.l.Info("Removing IPs from filter manager (excluded)", zap.String("namespace", n), zap.Any("ips", ips)) + + err := m.filterManager.DeleteIPs(ips, metricModuleReq, moduleReqMetadata) + if err != nil { + m.l.Error("Error removing IPs from filter manager", zap.Error(err)) + } + } + + // For newly un-excluded namespaces: add their IPs to filtermanager + for _, n := range newlyUnexcluded { + ips := m.daemonCache.GetIPsByNamespace(n) + m.l.Info("Adding IPs to filter manager (un-excluded)", zap.String("namespace", n), zap.Any("ips", ips)) + + err := m.filterManager.AddIPs(ips, metricModuleReq, moduleReqMetadata) + if err != nil { + m.l.Error("Error adding IPs to filter manager", zap.Error(err)) + } + } + + // When transitioning to exclude mode, add IPs for all non-excluded namespaces + if len(newlyExcluded) > 0 && len(newlyUnexcluded) == 0 && len(newlyExcluded) == len(ns) { + allNs := m.daemonCache.GetAllNamespaces() + for _, n := range allNs { + if _, excluded := m.excludedNamespaces[n]; !excluded { + ips := m.daemonCache.GetIPsByNamespace(n) + m.l.Info("Adding IPs to filter manager (non-excluded)", zap.String("namespace", n), zap.Any("ips", ips)) + + err := m.filterManager.AddIPs(ips, metricModuleReq, moduleReqMetadata) + if err != nil { + m.l.Error("Error adding IPs to filter manager", zap.Error(err)) + } + } + } + } } func (m *Module) PodCallBackFn(obj interface{}) { @@ -562,8 +618,10 @@ func (m *Module) applyDirtyPodsDelete() { m.dirtyPods.ClearDelete() } -// nsOfInterest checks if the namespace is in the included or excluded list -// included namespaces can be defined by crd or automatically applied by annotated namespaces. +// nsOfInterest checks if the namespace is in the included or excluded list. +// Included namespaces can be defined by CRD or automatically applied by annotated namespaces. +// When no namespace filters are configured (both lists empty), returns false — pods must be +// individually annotated or already present in the filtermap to be tracked. func (m *Module) nsOfInterest(ns string) bool { if len(m.includedNamespaces) > 0 { if _, ok := m.includedNamespaces[ns]; ok { diff --git a/pkg/module/metrics/metrics_module_linux_test.go b/pkg/module/metrics/metrics_module_linux_test.go index d6bd597efa..abc37b5552 100644 --- a/pkg/module/metrics/metrics_module_linux_test.go +++ b/pkg/module/metrics/metrics_module_linux_test.go @@ -658,3 +658,257 @@ func TestPodAnnotated(t *testing.T) { assert.Equal(t, tt.expected, tt.m.podAnnotated(tt.annotations)) } } + +func TestNsOfInterest(t *testing.T) { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + + tests := []struct { + name string + includedNamespaces map[string]struct{} + excludedNamespaces map[string]struct{} + ns string + expected bool + }{ + { + name: "no filters configured (empty maps) - no namespace is of interest", + includedNamespaces: map[string]struct{}{}, + excludedNamespaces: map[string]struct{}{}, + ns: "default", + expected: false, + }, + { + name: "no filters configured (nil maps) - no namespace is of interest", + includedNamespaces: nil, + excludedNamespaces: nil, + ns: "default", + expected: false, + }, + { + name: "included namespace matches", + includedNamespaces: map[string]struct{}{"ns1": {}}, + ns: "ns1", + expected: true, + }, + { + name: "included namespace does not match", + includedNamespaces: map[string]struct{}{"ns1": {}}, + ns: "ns2", + expected: false, + }, + { + name: "excluded namespace matches - should not be of interest", + excludedNamespaces: map[string]struct{}{"ns1": {}}, + ns: "ns1", + expected: false, + }, + { + name: "excluded namespace does not match - should be of interest", + excludedNamespaces: map[string]struct{}{"ns1": {}}, + ns: "ns2", + expected: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &Module{ + includedNamespaces: tt.includedNamespaces, + excludedNamespaces: tt.excludedNamespaces, + } + assert.Equal(t, tt.expected, m.nsOfInterest(tt.ns)) + }) + } +} + +func TestAppendExcludeList(t *testing.T) { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + cfg, err := kcfg.GetConfig(testCfgFile) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + c.EXPECT().GetIPsByNamespace(gomock.Any()).Return([]net.IP{}).AnyTimes() + c.EXPECT().GetAllNamespaces().Return([]string{}).AnyTimes() + fm.EXPECT().AddIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + fm.EXPECT().DeleteIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + testcases := []struct { + description string + namespaces []string + wantExcludedNamespaces map[string]struct{} + }{ + { + "input 0 namespaces", + []string{}, + map[string]struct{}{}, + }, + { + "input 1 namespace (add)", + []string{"ns1"}, + map[string]struct{}{"ns1": {}}, + }, + { + "input 1 namespace different than previous (add 1 & remove 1)", + []string{"ns2"}, + map[string]struct{}{"ns2": {}}, + }, + { + "input 2 namespaces (add 1)", + []string{"ns1", "ns2"}, + map[string]struct{}{"ns1": {}, "ns2": {}}, + }, + { + "input 0 namespaces (remove all)", + []string{}, + map[string]struct{}{}, + }, + } + + for _, test := range testcases { + t.Run(test.description, func(t *testing.T) { + me.appendExcludeList(test.namespaces) + assert.Equal(t, test.wantExcludedNamespaces, me.excludedNamespaces) + }) + } +} + +func TestUpdateNamespaceListsExclude(t *testing.T) { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + cfg, err := kcfg.GetConfig(testCfgFile) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + c.EXPECT().GetIPsByNamespace(gomock.Any()).Return([]net.IP{}).AnyTimes() + c.EXPECT().GetAllNamespaces().Return([]string{}).AnyTimes() + fm.EXPECT().AddIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + fm.EXPECT().DeleteIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + testcases := []struct { + description string + spec *api.MetricsSpec + wantIncludedNamespaces map[string]struct{} + wantExcludedNamespaces map[string]struct{} + }{ + { + "exclude only - should populate excludedNamespaces", + &api.MetricsSpec{ + Namespaces: api.MetricsNamespaces{ + Exclude: []string{"ns1"}, + }, + }, + map[string]struct{}{}, + map[string]struct{}{"ns1": {}}, + }, + { + "neither set - both empty", + &api.MetricsSpec{}, + map[string]struct{}{}, + map[string]struct{}{}, + }, + } + + for _, test := range testcases { + t.Run(test.description, func(t *testing.T) { + me.updateNamespaceLists(test.spec) + assert.Equal(t, test.wantIncludedNamespaces, me.includedNamespaces) + assert.Equal(t, test.wantExcludedNamespaces, me.excludedNamespaces) + }) + } +} + +func TestPodCallBackExclude(t *testing.T) { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + c.EXPECT().GetIPsByNamespace(gomock.Any()).Return([]net.IP{}).AnyTimes() + c.EXPECT().GetAllNamespaces().Return([]string{}).AnyTimes() + fm.EXPECT().AddIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + fm.EXPECT().DeleteIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + // Setup exclude list via updateNamespaceLists + spec := &api.MetricsSpec{ + Namespaces: api.MetricsNamespaces{ + Exclude: []string{"ns1"}, + }, + } + me.updateNamespaceLists(spec) + + // Pod in non-excluded namespace should be tracked + pod1 := common.NewRetinaEndpoint("pod1", "default", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 1)}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + adds := me.dirtyPods.GetAddList() + assert.Len(t, adds, 1, "pod in non-excluded namespace should be added to dirty pods") + + // Pod in excluded namespace should NOT be tracked + pod2 := common.NewRetinaEndpoint("pod2", "ns1", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 2)}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod2)) + adds = me.dirtyPods.GetAddList() + assert.Len(t, adds, 1, "pod in excluded namespace should not be added to dirty pods") +} From e9c57d7c7183a97fab85f8532127e05f7ecc8321 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:40:37 +0200 Subject: [PATCH 286/448] test: Add ebpf testing and improve coverage for ringbuf in packetparser (#2154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR adds testing support for eBPF ring buffers to the `packetparser` plugin. It introduces mechanisms to compile eBPF programs with ring buffer support enabled and verifies their execution using ring buffers instead of the traditional perf event buffers. ## Changes - **`pkg/plugin/ebpftest/helpers.go`**: Added the `ReadRingBufEvent` helper function to read events from a `ringbuf.Reader` with a timeout safely. - **`pkg/plugin/packetparser/packetparser_ebpf_test.go`**: - Extended eBPF test compilation options to support ring buffers by adding `-DUSE_RING_BUFFER` and size macros. - Refactored compilation functions (`compileAndLoadVariantBase`, `compileAndLoadVariant`, and `compileAndLoadRingBufVariant`) to manage both `perf.Reader` and `ringbuf.Reader` initialization depending on the configuration. - Added `TestEndpointIngressFilter_TCP_RingBuf`, a new test case that strictly validates `EndpointIngressFilter` behavior dynamically utilizing the eBPF ring buffer implementation. ### Test Coverage Enhancements - **`TestReadData_RingBufClosed`**: Validates safe extraction and handling of `ringbuf.ErrClosed` within the packet parser to avoid unexpected loops. - **`TestEnsureRingBufKernelSupported`**: Evaluates strict kernel version guarantees (≥ `5.8.0`) by mocking OS lookups to enforce ring buffer restrictions accurately. - **`TestRingBufReaderWrapper`**: Validates the conversion wrapper explicitly to ensure `RingBuf` logs map back consistently to the structured `perfRecord` definitions. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ```sh ❯ sudo -E go test -tags ebpf ./pkg/plugin/packetparser -v | grep -i ringbuf === RUN TestValidateRingBufferSize === RUN TestValidateRingBufferSize/Zero_input_returns_error === RUN TestValidateRingBufferSize/Below_page_size_returns_error === RUN TestValidateRingBufferSize/Above_max_size_returns_error === RUN TestValidateRingBufferSize/Not_power_of_2_returns_error === RUN TestValidateRingBufferSize/Valid_size_returns_no_error === RUN TestValidateRingBufferSize/Valid_max_size_returns_no_error === RUN TestValidateRingBufferSize/Valid_page_size_returns_no_error_(assuming_page_size_is_power_of_2) --- PASS: TestValidateRingBufferSize (0.00s) --- PASS: TestValidateRingBufferSize/Zero_input_returns_error (0.00s) --- PASS: TestValidateRingBufferSize/Below_page_size_returns_error (0.00s) --- PASS: TestValidateRingBufferSize/Above_max_size_returns_error (0.00s) --- PASS: TestValidateRingBufferSize/Not_power_of_2_returns_error (0.00s) --- PASS: TestValidateRingBufferSize/Valid_size_returns_no_error (0.00s) --- PASS: TestValidateRingBufferSize/Valid_max_size_returns_no_error (0.00s) --- PASS: TestValidateRingBufferSize/Valid_page_size_returns_no_error_(assuming_page_size_is_power_of_2) (0.00s) === RUN TestEndpointIngressFilter_TCP_RingBuf --- PASS: TestEndpointIngressFilter_TCP_RingBuf (0.44s) === RUN TestRingBufReaderWrapper --- PASS: TestRingBufReaderWrapper (0.43s) === RUN TestReadData_RingBufClosed --- PASS: TestReadData_RingBufClosed (0.00s) === RUN TestCompileRingBuffer --- PASS: TestCompileRingBuffer (0.22s) === RUN TestEnsureRingBufKernelSupported === RUN TestEnsureRingBufKernelSupported/Supported === RUN TestEnsureRingBufKernelSupported/Supported_newer === RUN TestEnsureRingBufKernelSupported/Not_supported_old_major === RUN TestEnsureRingBufKernelSupported/Not_supported_old_minor === RUN TestEnsureRingBufKernelSupported/Kernel_version_error --- PASS: TestEnsureRingBufKernelSupported (0.00s) --- PASS: TestEnsureRingBufKernelSupported/Supported (0.00s) --- PASS: TestEnsureRingBufKernelSupported/Supported_newer (0.00s) --- PASS: TestEnsureRingBufKernelSupported/Not_supported_old_major (0.00s) --- PASS: TestEnsureRingBufKernelSupported/Not_supported_old_minor (0.00s) --- PASS: TestEnsureRingBufKernelSupported/Kernel_version_error (0.00s) ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- pkg/plugin/ebpftest/helpers.go | 33 +++++ .../packetparser/packetparser_ebpf_test.go | 129 ++++++++++++++++-- pkg/plugin/packetparser/packetparser_linux.go | 4 +- .../packetparser/packetparser_linux_test.go | 65 +++++++++ 4 files changed, 221 insertions(+), 10 deletions(-) diff --git a/pkg/plugin/ebpftest/helpers.go b/pkg/plugin/ebpftest/helpers.go index d4fba5a9f1..ac316b0d8a 100644 --- a/pkg/plugin/ebpftest/helpers.go +++ b/pkg/plugin/ebpftest/helpers.go @@ -17,6 +17,7 @@ import ( "github.com/cilium/ebpf" "github.com/cilium/ebpf/perf" + "github.com/cilium/ebpf/ringbuf" "github.com/stretchr/testify/require" "golang.org/x/sys/unix" ) @@ -193,3 +194,35 @@ func ReadPerCPUMap[T any](t *testing.T, m *ebpf.Map, key uint32) (T, bool) { var zero T return zero, false } + +// ReadRingBufEvent reads one ringbuf record from the reader within the given timeout, +// decodes it into T using binary.Read (little-endian), and returns it. +// Returns (zero, false) if the deadline expires without an event. +func ReadRingBufEvent[T any](t *testing.T, rb *ringbuf.Reader, timeout time.Duration) (T, bool) { + t.Helper() + + type result struct { + rec ringbuf.Record + err error + } + + // ringbuf.Read is blocking, so we run it in a goroutine to support timeout. + // When the test ends or rb is closed, this should unblock. + ch := make(chan result, 1) + go func() { + rec, err := rb.Read() + ch <- result{rec, err} + }() + + select { + case res := <-ch: + require.NoError(t, res.err) + var event T + err := binary.Read(bytes.NewReader(res.rec.RawSample), binary.LittleEndian, &event) + require.NoError(t, err) + return event, true + case <-time.After(timeout): + // Caller should cleanup reader to stop the goroutine + return *new(T), false + } +} diff --git a/pkg/plugin/packetparser/packetparser_ebpf_test.go b/pkg/plugin/packetparser/packetparser_ebpf_test.go index 6f3110b7c3..d7a6f056e1 100644 --- a/pkg/plugin/packetparser/packetparser_ebpf_test.go +++ b/pkg/plugin/packetparser/packetparser_ebpf_test.go @@ -18,6 +18,7 @@ import ( "github.com/cilium/ebpf" "github.com/cilium/ebpf/perf" + "github.com/cilium/ebpf/ringbuf" "github.com/gopacket/gopacket/layers" "github.com/microsoft/retina/pkg/loader" "github.com/microsoft/retina/pkg/log" @@ -612,12 +613,13 @@ type compileOpts struct { enableConntrack bool aggregationLevel int samplingRate int + enableRingBuf bool } -// compileAndLoadVariant compiles the packetparser eBPF program with custom -// dynamic.h settings and returns loaded objects + perf reader. +// compileAndLoadVariantBase compiles the packetparser eBPF program with custom +// dynamic.h settings and returns loaded objects + perf/ringbuf reader. // Requires clang to be installed. -func compileAndLoadVariant(t *testing.T, opts compileOpts) (*packetparserObjects, *perf.Reader) { +func compileAndLoadVariantBase(t *testing.T, opts compileOpts) (*packetparserObjects, *perf.Reader, *ringbuf.Reader) { t.Helper() ebpftest.RequirePrivileged(t) @@ -666,7 +668,8 @@ func compileAndLoadVariant(t *testing.T, opts compileOpts) (*packetparserObjects } log.SetupZapLogger(log.GetDefaultLogOpts()) //nolint:errcheck - err = loader.CompileEbpf(context.Background(), + + cflags := []string{ "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, "-o", outputFile, fmt.Sprintf("-I%s/../lib/_%s", dir, arch), @@ -676,7 +679,12 @@ func compileAndLoadVariant(t *testing.T, opts compileOpts) (*packetparserObjects fmt.Sprintf("-I%s/../lib/common/libbpf/_include/asm", dir), fmt.Sprintf("-I%s/../filter/_cprog/", dir), fmt.Sprintf("-I%s/../conntrack/_cprog/", dir), - ) + } + if opts.enableRingBuf { + cflags = append(cflags, "-DUSE_RING_BUFFER", "-DRING_BUFFER_SIZE=4096") + } + + err = loader.CompileEbpf(context.Background(), cflags...) require.NoError(t, err, "failed to compile eBPF program") // Load the compiled object. @@ -689,11 +697,30 @@ func compileAndLoadVariant(t *testing.T, opts compileOpts) (*packetparserObjects require.NoError(t, err) t.Cleanup(func() { objs.Close() }) - reader, err := perf.NewReader(objs.RetinaPacketparserEvents, os.Getpagesize()*4) - require.NoError(t, err) - t.Cleanup(func() { reader.Close() }) + var pReader *perf.Reader + var rReader *ringbuf.Reader + if opts.enableRingBuf { + rReader, err = ringbuf.NewReader(objs.RetinaPacketparserEvents) + require.NoError(t, err) + t.Cleanup(func() { rReader.Close() }) + } else { + pReader, err = perf.NewReader(objs.RetinaPacketparserEvents, os.Getpagesize()*4) + require.NoError(t, err) + t.Cleanup(func() { pReader.Close() }) + } - return &objs, reader + return &objs, pReader, rReader +} + +func compileAndLoadVariant(t *testing.T, opts compileOpts) (*packetparserObjects, *perf.Reader) { + objs, pReader, _ := compileAndLoadVariantBase(t, opts) + return objs, pReader +} + +func compileAndLoadRingBufVariant(t *testing.T, opts compileOpts) (*packetparserObjects, *ringbuf.Reader) { + opts.enableRingBuf = true + objs, _, rReader := compileAndLoadVariantBase(t, opts) + return objs, rReader } func TestConntrackMetricsEnabled(t *testing.T) { @@ -1188,3 +1215,87 @@ func TestConntrackEvictionTimeExtended(t *testing.T) { "eviction time should increase after ACK (60s SYN timeout → 360s established), got %d → %d", synEviction, entry.EvictionTime) } + +func TestEndpointIngressFilter_TCP_RingBuf(t *testing.T) { + if err := ensureRingBufKernelSupported(); err != nil { + t.Skipf("ring buffer not supported: %v", err) + } + + objs, reader := compileAndLoadRingBufVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: false, + aggregationLevel: 0, + samplingRate: 1, + }) + + srcIP := net.ParseIP("10.0.0.1") + dstIP := net.ParseIP("10.0.0.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 12345, + DstPort: 80, + SYN: true, + SeqNum: 1000, + }) + + // Run program + ret := ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + assert.Equal(t, uint32(tcActUnspec), ret, "expected TC_ACT_UNSPEC return value") + + // Read event from Ring Buffer + event, ok := ebpftest.ReadRingBufEvent[packetparserPacket](t, reader, perfReaderTimeout) + require.True(t, ok, "expected a ringbuf event") + + assert.Equal(t, ebpftest.IPToNative("10.0.0.1"), event.SrcIp) + assert.Equal(t, ebpftest.IPToNative("10.0.0.2"), event.DstIp) + assert.Equal(t, ebpftest.PortToNetwork(12345), event.SrcPort) + assert.Equal(t, ebpftest.PortToNetwork(80), event.DstPort) + assert.Equal(t, uint8(protoTCP), event.Proto) +} + +func TestRingBufReaderWrapper(t *testing.T) { + if err := ensureRingBufKernelSupported(); err != nil { + t.Skipf("ring buffer not supported: %v", err) + } + + objs, reader := compileAndLoadRingBufVariant(t, compileOpts{ + bypassFilter: 1, + enableConntrack: false, + aggregationLevel: 0, + samplingRate: 1, + }) + + wrapper := &ringBufReaderWrapper{reader: reader} + + srcIP := net.ParseIP("10.0.0.1") + dstIP := net.ParseIP("10.0.0.2") + ebpftest.PopulateFilterMap(t, objs.RetinaFilter, srcIP, dstIP) + + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: srcIP, + DstIP: dstIP, + SrcPort: 54321, + DstPort: 80, + SYN: true, + SeqNum: 2000, + }) + + // Run program to generate an event + ebpftest.RunProgram(t, objs.EndpointIngressFilter, pkt) + + // Test Read() behavior + rec, err := wrapper.Read() + require.NoError(t, err) + require.NotNil(t, rec.RawSample) + + // Test Close() behavior + err = wrapper.Close() + require.NoError(t, err) + + // After closing, Read() should return ringbuf.ErrClosed + _, err = wrapper.Read() + assert.ErrorIs(t, err, ringbuf.ErrClosed) +} diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index f4bf4a2beb..0eb0fb1d27 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -995,8 +995,10 @@ func (r *perfReaderWrapper) Close() error { return nil } +var getKernelVersion = utils.LinuxKernelVersion + func ensureRingBufKernelSupported() error { - kv, err := utils.LinuxKernelVersion() + kv, err := getKernelVersion() if err != nil { return fmt.Errorf("failed to detect kernel version for ring buffer support: %w", err) } diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go index 2f54dbba58..4fa4a5394c 100644 --- a/pkg/plugin/packetparser/packetparser_linux_test.go +++ b/pkg/plugin/packetparser/packetparser_linux_test.go @@ -18,6 +18,7 @@ import ( v1 "github.com/cilium/cilium/pkg/hubble/api/v1" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/ringbuf" tc "github.com/florianl/go-tc" nl "github.com/mdlayher/netlink" kcfg "github.com/microsoft/retina/pkg/config" @@ -25,6 +26,7 @@ import ( "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/metrics" "github.com/microsoft/retina/pkg/plugin/packetparser/mocks" + "github.com/microsoft/retina/pkg/utils" "github.com/microsoft/retina/pkg/watchers/endpoint" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" @@ -354,6 +356,25 @@ func TestReadData_Error(t *testing.T) { p.readData() } +func TestReadData_RingBufClosed(t *testing.T) { + log.SetupZapLogger(log.GetDefaultLogOpts()) //nolint:errcheck // ignore + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mperf := newMockPerfReader(ctrl) + mperf.EXPECT().Read().Return(perfRecord{}, ringbuf.ErrClosed).AnyTimes() + + menricher := enricher.NewMockEnricherInterface(ctrl) //nolint:typecheck + menricher.EXPECT().Write(gomock.Any()).Times(0) + + p := &packetParser{ + cfg: cfgRingBufferEnabled, + l: log.Logger().Named("test"), + reader: mperf, + } + p.readData() +} + func TestReadDataPodLevelEnabled(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) ctrl := gomock.NewController(t) @@ -733,6 +754,50 @@ func TestCompileRingBuffer(t *testing.T) { } } +func TestEnsureRingBufKernelSupported(t *testing.T) { + orig := getKernelVersion + defer func() { getKernelVersion = orig }() + + tests := []struct { + name string + major int + minor int + patch int + errExists bool + }{ + {"Supported", 5, 8, 0, false}, + {"Supported newer", 6, 1, 0, false}, + {"Not supported old major", 4, 15, 0, true}, + {"Not supported old minor", 5, 7, 0, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + getKernelVersion = func() (utils.KernelVersion, error) { + return utils.KernelVersion{ + Major: tt.major, + Minor: tt.minor, + Patch: tt.patch, + }, nil + } + err := ensureRingBufKernelSupported() + if tt.errExists { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } + + t.Run("Kernel version error", func(t *testing.T) { + getKernelVersion = func() (utils.KernelVersion, error) { + return utils.KernelVersion{}, errors.New("failed to get kernel version") //nolint:err113 // ignore + } + err := ensureRingBufKernelSupported() + assert.Error(t, err) + }) +} + // Helpers. func takeBackup() { // Get the directory of the current test file. From 77c13ff4eabb7bd11e3cfee11b08af75d5b85417 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:06:33 -0400 Subject: [PATCH 287/448] chore(deps): Bump lodash from 4.17.23 to 4.18.1 in /site in the npm_and_yarn group across 1 directory (#2156) Bumps the npm_and_yarn group with 1 update in the /site directory: [lodash](https://github.com/lodash/lodash). Updates `lodash` from 4.17.23 to 4.18.1
Release notes

Sourced from lodash's releases.

4.18.1

Bugs

Fixes a ReferenceError issue in lodash lodash-es lodash-amd and lodash.template when using the template and fromPairs functions from the modular builds. See lodash/lodash#6167

These defects were related to how lodash distributions are built from the main branch using https://github.com/lodash-archive/lodash-cli. When internal dependencies change inside lodash functions, equivalent updates need to be made to a mapping in the lodash-cli. (hey, it was ahead of its time once upon a time!). We know this, but we missed it in the last release. It's the kind of thing that passes in CI, but fails bc the build is not the same thing you tested.

There is no diff on main for this, but you can see the diffs for each of the npm packages on their respective branches:

4.18.0

v4.18.0

Full Changelog: https://github.com/lodash/lodash/compare/4.17.23...4.18.0

Security

_.unset / _.omit: Fixed prototype pollution via constructor/prototype path traversal (GHSA-f23m-r3pf-42rh, fe8d32e). Previously, array-wrapped path segments and primitive roots could bypass the existing guards, allowing deletion of properties from built-in prototypes. Now constructor and prototype are blocked unconditionally as non-terminal path keys, matching baseSet. Calls that previously returned true and deleted the property now return false and leave the target untouched.

_.template: Fixed code injection via imports keys (GHSA-r5fr-rjxr-66jc, CVE-2026-4800, 879aaa9). Fixes an incomplete patch for CVE-2021-23337. The variable option was validated against reForbiddenIdentifierChars but importsKeys was left unguarded, allowing code injection via the same Function() constructor sink. imports keys containing forbidden identifier characters now throw "Invalid imports option passed into _.template".

Docs

  • Add security notice for _.template in threat model and API docs (#6099)
  • Document lower > upper behavior in _.random (#6115)
  • Fix quotes in _.compact jsdoc (#6090)

lodash.* modular packages

Diff

We have also regenerated and published a select number of the lodash.* modular packages.

These modular packages had fallen out of sync significantly from the minor/patch updates to lodash. Specifically, we have brought the following packages up to parity w/ the latest lodash release because they have had CVEs on them in the past:

Commits
  • cb0b9b9 release(patch): bump main to 4.18.1 (#6177)
  • 75535f5 chore: prune stale advisory refs (#6170)
  • 62e91bc docs: remove n_ Node.js < 6 REPL note from README (#6165)
  • 59be2de release(minor): bump to 4.18.0 (#6161)
  • af63457 fix: broken tests for _.template 879aaa9
  • 1073a76 fix: linting issues
  • 879aaa9 fix: validate imports keys in _.template
  • fe8d32e fix: block prototype pollution in baseUnset via constructor/prototype traversal
  • 18ba0a3 refactor(fromPairs): use baseAssignValue for consistent assignment (#6153)
  • b819080 ci: add dist sync validation workflow (#6137)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lodash&package-manager=npm_and_yarn&previous-version=4.17.23&new-version=4.18.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index dd1bb88529..0b1afe36bc 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -11053,9 +11053,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.debounce": { From 86333aa57c3bc1f39ab3c18546dfe3537a940518 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:57:16 +0200 Subject: [PATCH 288/448] feat(ebpf): generate vmlinux.h in init container (#1984) ## Description This PR finalizes Retina's runtime `vmlinux.h` workflow for CO-RE-safe eBPF compilation while keeping the main agent runtime image minimal. `vmlinux.h` is generated from host BTF via `bpftool` in the **init container**, persisted under `/tmp/retina/include`, and consumed by plugin compile paths. The loader now caches generation metadata and skips regeneration when the cached header matches the current kernel release, regenerating automatically on kernel drift. This avoids static-header CO-RE relocation issues and removes the need for `bpftool` in the main agent runtime image. ## What Changed - Added runtime `vmlinux.h` support in `pkg/loader`: - `GenerateVmlinuxH(ctx, outputDir)` - runtime path constants/helpers (`DefaultVmlinuxHeaderDir`, `VmlinuxHeaderDir`, `VmlinuxHeaderPath`) - `PrepareVmlinuxH(ctx)` for ensure-or-generate behavior - Added cache drift detection in `pkg/loader`: - stores kernel release metadata in `vmlinux.kernel.release` - reuses cached `vmlinux.h` only when current kernel release matches cached value - regenerates `vmlinux.h` on mismatch/missing cache metadata - Added generation duration logging in loader (`Generated vmlinux.h` with elapsed time) for startup observability. - Added loader unit test coverage for runtime header generation (`pkg/loader/vmlinux_test.go`). - Added init-container generation call in `init/retina/main_linux.go` so header creation happens before the agent starts. - Removed plugin-manager-side `vmlinux.h` generation from agent startup. - Updated plugin compile paths to include runtime header directory (dropreason, packetforward, packetparser) without per-plugin `GenerateVmlinuxH` calls. - Updated Helm daemonsets (standard + hubble) to mount shared `/tmp` into both init and agent containers so generated headers are available to the agent. - Updated container packaging so `bpftool` is available to init runtime but not bundled into the agent runtime bin set: - init image receives `bpftool` - agent `/bin` bundle excludes `bpftool` ## Operational Notes - Init logs now include runtime `vmlinux.h` preparation and generation duration. - Agent compiles plugins using `-I/tmp/retina/include` (or `RETINA_VMLINUX_HEADER_DIR` override) without requiring `bpftool` in agent runtime. - Cache behavior: - same kernel release: skip regeneration - kernel release drift: regenerate and refresh metadata ## Commit Summary (PR) - fe478053 feat(bpf): generate vmlinux.h at runtime - a79b499f fix linting - 3bf8411b refactor(ebpf): centralize vmlinux.h generation and share runtime include path - 79d851fe generate vmlinux.h in init and remove bpftool from agent runtime - 65127ed3 cache vmlinux.h by kernel release and log generation duration - 0cead17c return accurate vmlinux generation error and defer logging to caller Fixes #1777 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Container retina-init logs + curl to show retina metrics are generated: image Check `vmlinux.h` exist under `/tmp/retina/include` within the retina-agent Pod: image Debug logs to show plugins compile using header location `/tmp/retina/include`: Screenshot 2026-04-02 165513 ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- controller/Dockerfile | 4 + .../retina/templates/agent/daemonset.yaml | 6 + .../helm/retina/templates/daemonset.yaml | 2 + init/retina/main_linux.go | 13 ++ pkg/loader/vmlinux.go | 147 ++++++++++++++++++ pkg/loader/vmlinux_test.go | 38 +++++ pkg/plugin/dropreason/dropreason_linux.go | 9 +- .../packetforward/packetforward_linux.go | 9 +- pkg/plugin/packetparser/packetparser_linux.go | 4 + 9 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 pkg/loader/vmlinux.go create mode 100644 pkg/loader/vmlinux_test.go diff --git a/controller/Dockerfile b/controller/Dockerfile index d6b958140c..b6acdf58c2 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -70,6 +70,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /go/bin/ret FROM azurelinux-core AS tools RUN tdnf install -y \ clang \ + bpftool \ iproute \ iptables \ tcpdump \ @@ -83,6 +84,8 @@ RUN arr="clang tcpdump ip ss iptables-legacy iptables-legacy-save iptables-nft i for i in $arr; do \ cp $(which $i) /tmp/bin; \ done +RUN mkdir -p /tmp/init-bin +RUN cp $(which bpftool) /tmp/init-bin # Download Hubble ARG GOARCH=amd64 ENV HUBBLE_ARCH=${GOARCH} @@ -102,6 +105,7 @@ COPY --from=init-bin /go/bin/retina/initretina /retina/initretina COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib COPY --from=tools /etc/pki/tls/ /etc/pki/tls/ +COPY --from=tools /tmp/init-bin/ /bin/ ENTRYPOINT ["./retina/initretina"] # agent final image diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml index f9bed3a751..6e5fe415ae 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml @@ -54,6 +54,8 @@ spec: mountPath: /var/run/cilium - name: config mountPath: /retina/config + - name: tmp + mountPath: /tmp containers: - name: {{ include "retina.name" . }} image: {{ .Values.agent.repository }}:{{ .Values.agent.tag }} @@ -125,6 +127,8 @@ spec: mountPath: /var/run/cilium - name: host-os-release mountPath: /etc/os-release + - name: tmp + mountPath: /tmp {{- if .Values.hubble.tls.enabled }} - name: tls mountPath: /var/lib/cilium/tls/hubble @@ -155,6 +159,8 @@ spec: hostPath: path: /etc/os-release type: FileOrCreate + - name: tmp + emptyDir: {} {{- if .Values.hubble.tls.enabled }} - name: tls projected: diff --git a/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml b/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml index 3574142463..fece02726d 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/daemonset.yaml @@ -45,6 +45,8 @@ spec: mountPropagation: Bidirectional - name: config mountPath: /retina/config + - name: tmp + mountPath: /tmp containers: - name: {{ include "retina.name" . }} readinessProbe: diff --git a/init/retina/main_linux.go b/init/retina/main_linux.go index 7a2a3afb8a..f284b54a5c 100644 --- a/init/retina/main_linux.go +++ b/init/retina/main_linux.go @@ -4,6 +4,7 @@ package main import ( + "context" "flag" "fmt" "os" @@ -11,6 +12,7 @@ import ( "github.com/microsoft/retina/internal/buildinfo" "github.com/microsoft/retina/pkg/bpf" "github.com/microsoft/retina/pkg/config" + "github.com/microsoft/retina/pkg/loader" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/telemetry" "github.com/pkg/errors" @@ -63,5 +65,16 @@ func run(args ...string) error { return errors.Wrap(err, "failed to setup Retina bpf filesystem") } + runtimeHeaderDir, headerErr := loader.PrepareVmlinuxH(context.Background()) + if headerErr != nil { + l.Warn( + "failed to prepare runtime vmlinux.h in init container, falling back to static headers", + zap.String("path", runtimeHeaderDir), + zap.Error(headerErr), + ) + } else { + l.Info("prepared runtime vmlinux.h in init container", zap.String("path", loader.VmlinuxHeaderPath())) + } + return nil } diff --git a/pkg/loader/vmlinux.go b/pkg/loader/vmlinux.go new file mode 100644 index 0000000000..4953a1f2c8 --- /dev/null +++ b/pkg/loader/vmlinux.go @@ -0,0 +1,147 @@ +package loader + +import ( + "context" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/microsoft/retina/pkg/log" + "go.uber.org/zap" +) + +const ( + // DefaultVmlinuxHeaderDir is the default runtime include directory used by plugins. + DefaultVmlinuxHeaderDir = "/tmp/retina/include" + // VmlinuxHeaderDirEnv is an optional env var to override the runtime include directory. + VmlinuxHeaderDirEnv = "RETINA_VMLINUX_HEADER_DIR" + // VmlinuxHeaderFileName is the generated runtime BTF header filename. + VmlinuxHeaderFileName = "vmlinux.h" + // VmlinuxKernelReleaseFileName stores the kernel release used to generate vmlinux.h. + VmlinuxKernelReleaseFileName = "vmlinux.kernel.release" + kernelReleasePath = "/proc/sys/kernel/osrelease" +) + +var ( + errKernelReleaseEmpty = errors.New("kernel release is empty") + errCachedKernelReleaseEmpty = errors.New("cached kernel release is empty") +) + +// VmlinuxHeaderDir returns the runtime directory where vmlinux.h is expected. +func VmlinuxHeaderDir() string { + dir := strings.TrimSpace(os.Getenv(VmlinuxHeaderDirEnv)) + if dir == "" { + return DefaultVmlinuxHeaderDir + } + + return dir +} + +// VmlinuxHeaderPath returns the full runtime path to vmlinux.h. +func VmlinuxHeaderPath() string { + return filepath.Join(VmlinuxHeaderDir(), VmlinuxHeaderFileName) +} + +// PrepareVmlinuxH ensures runtime vmlinux.h exists and returns the include dir. +func PrepareVmlinuxH(ctx context.Context) (string, error) { + headerDir := VmlinuxHeaderDir() + headerPath := filepath.Join(headerDir, VmlinuxHeaderFileName) + kernelRelease, err := currentKernelRelease() + if err != nil { + return headerDir, err + } + + if info, err := os.Stat(headerPath); err == nil { + if info.Size() > 0 { + cachedKernelRelease, readErr := readCachedKernelRelease(headerDir) + if readErr == nil && cachedKernelRelease == kernelRelease { + return headerDir, nil + } + } + } else if !errors.Is(err, os.ErrNotExist) { + return headerDir, fmt.Errorf("failed to stat %s: %w", headerPath, err) + } + + if err := GenerateVmlinuxH(ctx, headerDir); err != nil { + return headerDir, err + } + + if err := writeCachedKernelRelease(headerDir, kernelRelease); err != nil { + return headerDir, err + } + + return headerDir, nil +} + +func GenerateVmlinuxH(ctx context.Context, outputDir string) error { + l := log.Logger().Named("vmlinux-generator") + vmlinuxPath := filepath.Join(outputDir, VmlinuxHeaderFileName) + start := time.Now() + + if err := os.MkdirAll(outputDir, 0o755); err != nil { + return fmt.Errorf("failed to create output directory: %w", err) + } + + cmd := exec.CommandContext(ctx, "bpftool", "btf", "dump", "file", "/sys/kernel/btf/vmlinux", "format", "c") + + outfile, err := os.Create(vmlinuxPath) + if err != nil { + return fmt.Errorf("failed to create vmlinux.h: %w", err) + } + defer outfile.Close() + + cmd.Stdout = outfile + // Capture stderr for debugging + cmd.Stderr = os.Stderr + + l.Info("Generating vmlinux.h", zap.String("path", vmlinuxPath)) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to generate vmlinux.h: %w", err) + } + + l.Info("Generated vmlinux.h", zap.String("path", vmlinuxPath), zap.Duration("duration", time.Since(start))) + + return nil +} + +func currentKernelRelease() (string, error) { + b, err := os.ReadFile(kernelReleasePath) + if err != nil { + return "", fmt.Errorf("failed to read %s: %w", kernelReleasePath, err) + } + + release := strings.TrimSpace(string(b)) + if release == "" { + return "", fmt.Errorf("%w: %s", errKernelReleaseEmpty, kernelReleasePath) + } + + return release, nil +} + +func readCachedKernelRelease(outputDir string) (string, error) { + metaPath := filepath.Join(outputDir, VmlinuxKernelReleaseFileName) + b, err := os.ReadFile(metaPath) + if err != nil { + return "", fmt.Errorf("failed to read cached kernel release %s: %w", metaPath, err) + } + + release := strings.TrimSpace(string(b)) + if release == "" { + return "", errCachedKernelReleaseEmpty + } + + return release, nil +} + +func writeCachedKernelRelease(outputDir, kernelRelease string) error { + metaPath := filepath.Join(outputDir, VmlinuxKernelReleaseFileName) + if err := os.WriteFile(metaPath, []byte(kernelRelease+"\n"), 0o600); err != nil { + return fmt.Errorf("failed to write cached kernel release %s: %w", metaPath, err) + } + + return nil +} diff --git a/pkg/loader/vmlinux_test.go b/pkg/loader/vmlinux_test.go new file mode 100644 index 0000000000..ac505391b0 --- /dev/null +++ b/pkg/loader/vmlinux_test.go @@ -0,0 +1,38 @@ +package loader + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/microsoft/retina/pkg/log" + "github.com/stretchr/testify/require" +) + +func TestGenerateVmlinuxH(t *testing.T) { + // Initialize logger for test + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + + // Create a temporary directory for output + tmpDir, err := os.MkdirTemp("", "vmlinux-test") + require.NoError(t, err) + defer os.RemoveAll(tmpDir) + + ctx := context.Background() + err = GenerateVmlinuxH(ctx, tmpDir) + require.NoError(t, err) + + // Check if vmlinux.h exists + vmlinuxPath := filepath.Join(tmpDir, "vmlinux.h") + info, err := os.Stat(vmlinuxPath) + require.NoError(t, err) + require.False(t, info.IsDir()) + require.Positive(t, info.Size()) + + // Optional: Check content starts with typedef or similar C code + content, err := os.ReadFile(vmlinuxPath) + require.NoError(t, err) + require.Contains(t, string(content), "typedef") +} diff --git a/pkg/plugin/dropreason/dropreason_linux.go b/pkg/plugin/dropreason/dropreason_linux.go index d0b784a78e..aadf48ae2f 100644 --- a/pkg/plugin/dropreason/dropreason_linux.go +++ b/pkg/plugin/dropreason/dropreason_linux.go @@ -117,8 +117,15 @@ func (dr *dropReason) Compile(ctx context.Context) error { if arch == "arm64" { targetArch = "-D__TARGET_ARCH_arm64" } + + runtimeIncludeDir := "-I" + loader.VmlinuxHeaderDir() + // Keep target as bpf, otherwise clang compilation yields bpf object that elf reader cannot load. - err = loader.CompileEbpf(ctx, "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, "-o", bpfOutputFile, includeDir, libbpfDir, filterDir) + err = loader.CompileEbpf( + ctx, + "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, + "-o", bpfOutputFile, runtimeIncludeDir, includeDir, libbpfDir, filterDir, + ) if err != nil { return errors.Wrap(err, "unable to compile eBPF code") } diff --git a/pkg/plugin/packetforward/packetforward_linux.go b/pkg/plugin/packetforward/packetforward_linux.go index 3e14aee541..b94592fda0 100644 --- a/pkg/plugin/packetforward/packetforward_linux.go +++ b/pkg/plugin/packetforward/packetforward_linux.go @@ -124,8 +124,15 @@ func (p *packetForward) Compile(ctx context.Context) error { if arch == "arm64" { targetArch = "-D__TARGET_ARCH_arm64" } + + runtimeIncludeDir := "-I" + loader.VmlinuxHeaderDir() + // Keep target as bpf, otherwise clang compilation yields bpf object that elf reader cannot load. - err = loader.CompileEbpf(ctx, "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, "-o", bpfOutputFile, includeDir, libbpfDir) + err = loader.CompileEbpf( + ctx, + "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, + "-o", bpfOutputFile, runtimeIncludeDir, includeDir, libbpfDir, + ) if err != nil { return errors.Wrap(err, "error compiling ebpf code") } diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go index 0eb0fb1d27..005f708542 100644 --- a/pkg/plugin/packetparser/packetparser_linux.go +++ b/pkg/plugin/packetparser/packetparser_linux.go @@ -191,9 +191,13 @@ func (p *packetParser) Compile(ctx context.Context) error { if arch == "arm64" { targetArch = "-D__TARGET_ARCH_arm64" } + + runtimeIncludeDir := "-I" + loader.VmlinuxHeaderDir() + // Keep target as bpf, otherwise clang compilation yields bpf object that elf reader cannot load. cflags := []string{ "-target", "bpf", "-Wall", targetArch, "-g", "-O2", "-c", bpfSourceFile, "-o", bpfOutputFile, + runtimeIncludeDir, archLibDir, libbpfSrcDir, libbpfIncludeAsmDir, From 67ff3227f3e8e6aa7daa20ec22cafe0d9d678c5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 12:42:18 -0400 Subject: [PATCH 289/448] deps: Bump actions/setup-go from 6.3.0 to 6.4.0 (#2157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.3.0 to 6.4.0.
Release notes

Sourced from actions/setup-go's releases.

v6.4.0

What's Changed

Enhancement

Dependency update

Documentation update

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v6...v6.4.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=6.3.0&new-version=6.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/generate-check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-check.yaml b/.github/workflows/generate-check.yaml index a80585f4f6..d337b2e9fc 100644 --- a/.github/workflows/generate-check.yaml +++ b/.github/workflows/generate-check.yaml @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod From ab10de788ca14d6de84fec12115cba7482966b54 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Fri, 3 Apr 2026 12:49:56 -0400 Subject: [PATCH 290/448] chore(deps): bump Go builder to 1.26.1 and update base images (#2151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Go 1.26.0 has 4 stdlib CVEs with fixes in 1.26.1 (CVE-2026-25679, CVE-2026-27137, CVE-2026-27138, CVE-2026-27142). This PR bumps the Go builder images to 1.26.1 and updates all base image digests to latest. Image digest updates: - `oss/go/microsoft/golang` 1.26.0 → 1.26.1 (azurelinux3.0, plain, windowsservercore-ltsc2022) - `azurelinux/base/core:3.0` → latest digest - `azurelinux/distroless/minimal:3.0` → latest digest - `windows/nanoserver:ltsc2022` → latest digest - `windows/servercore:ltsc2022` → latest digest - `mirror/docker/library/ubuntu:24.04` → pinned by digest (was tag-only) Also adds `make bump-images` (`scripts/bump-images.sh`) which: 1. Checks for newer Go minor/patch versions from the registry and prompts the user to select which version to bump to 2. Parses the `# skopeo inspect ...` comments in Dockerfiles and auto-updates digests from the registry (handles `--override-os windows` automatically) ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Testing Completed ``` $ ./scripts/bump-images.sh Current Go builder version: 1.24.0 (mcr.microsoft.com/oss/go/microsoft/golang) Newer Go versions available: 1) 1.24.1 (patch) ... 13) 1.24.13 (patch) 14) 1.25.0 (minor) ... 22) 1.25.8 (minor) 23) 1.26.0 (minor) 24) 1.26.1 (minor) 0) Keep current (1.24.0) Select version to bump to [0]: 24 Bumping Go version: 1.24.0 → 1.26.1 GO cli/Dockerfile: 1.24.0 → 1.26.1 ... ``` ## Additional Notes N/A Signed-off-by: Quang Nguyen --- Makefile | 3 + cli/Dockerfile | 10 +- controller/Dockerfile | 10 +- controller/Dockerfile.gogen | 4 +- controller/Dockerfile.proto | 4 +- controller/Dockerfile.windows-2022 | 2 +- controller/Dockerfile.windows-cgo | 4 +- controller/Dockerfile.windows-native | 6 +- .../Dockerfile.windows-retina-oss-build | 2 +- hack/tools/kapinger/Dockerfile | 10 +- hack/tools/toolbox/Dockerfile | 7 +- operator/Dockerfile | 6 +- operator/Dockerfile.windows-2022 | 6 +- scripts/bump-images.sh | 191 ++++++++++++++++++ shell/Dockerfile | 2 +- test/image/Dockerfile | 4 +- 16 files changed, 233 insertions(+), 38 deletions(-) create mode 100755 scripts/bump-images.sh diff --git a/Makefile b/Makefile index a49bace34d..90d1254d66 100644 --- a/Makefile +++ b/Makefile @@ -148,6 +148,9 @@ lint-existing: ## Lint the current branch in entirety. clean: ## clean build artifacts $(RMDIR) $(OUTPUT_DIR) +bump-images: ## update all Dockerfile base image digests to latest + @./scripts/bump-images.sh + ##@ Build Binaries retina: ## builds retina binary diff --git a/cli/Dockerfile b/cli/Dockerfile index 5c924385e0..ad7042741c 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,11 +25,11 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # minimal libs stage — provides only the system libraries needed by the CGO-enabled binary, # without the bloat of the full Go SDK image (python, gcc, systemd, etc.) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 AS libs +FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS libs # Target 1: Distroless (secure, minimal) # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba AS distroless-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b AS distroless-target COPY --from=libs /lib/ /lib COPY --from=libs /usr/lib/ /usr/lib COPY --from=libs /etc/pki/tls/ /etc/pki/tls/ @@ -38,7 +38,7 @@ COPY --from=builder /workspace/kubectl-retina . # Target 2: Shell-enabled (operational, init container support) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 AS shell-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS shell-target WORKDIR / COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina RUN chmod +x /bin/kubectl-retina diff --git a/controller/Dockerfile b/controller/Dockerfile index b6acdf58c2..a56591d69b 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,13 +1,13 @@ # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba AS azurelinux-distroless +FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b AS azurelinux-distroless # build stages @@ -110,7 +110,7 @@ ENTRYPOINT ["./retina/initretina"] # agent final image # mcr.microsoft.com/azurelinux/distroless/minimal:3.0 -# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba +# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b FROM azurelinux-distroless AS agent COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index d07bbe0e3d..9dbf6616e4 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index e7055c7f5d..9f19d9eced 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 3767bbb20d..3341d93cb3 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,6 +1,6 @@ # pinned base image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:d4c6d1a8a1a306b12691c3b2e5e3a8bfad786cbd6b7831cd74a9a6a99eab08ad AS ltsc2022 FROM ltsc2022 AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index b2315c52a6..85a65f2236 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:179ddfa34eda50f58ea0011202f559585ade9668a298fe81ac01cebdc9bef15c AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 14af6943b3..c0e3e99513 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:179ddfa34eda50f58ea0011202f559585ade9668a298fe81ac01cebdc9bef15c AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:60612a30303eb5a15ce7f53fa2eecf70bca41d72657de0482fbde601ae5f3403 AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:be41510eb214c55def9162ef1fb5e71f1b71ce4d64d91bc963199f2383e034ea AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index c98ffe727a..4688e32709 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -3,7 +3,7 @@ ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore@sha256:d4c6d1a8a1a306b12691c3b2e5e3a8bfad786cbd6b7831cd74a9a6a99eab08ad AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 640633867d..f289be43dc 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:9644874dae39c9ef28b59836911bc859c0a6c5c1c1d76429063f4b435275815b AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS builder WORKDIR /build ADD . . @@ -16,8 +16,8 @@ COPY --from=builder /build/kapinger . CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:66a04c4bcea1fafc935246c96af236eb4d91d501387e061ae59f134c8993dae9 AS windows-builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS windows-builder WORKDIR /build ADD . . @@ -25,7 +25,7 @@ RUN go mod download RUN GOOS=windows go build -o kapinger.exe . # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:a264df8cd8c329eed3fd1e0cafcd4f3dc453e2c72a277f9bb140fd6f10a2eefc AS windows +FROM mcr.microsoft.com/windows/servercore@sha256:d4c6d1a8a1a306b12691c3b2e5e3a8bfad786cbd6b7831cd74a9a6a99eab08ad AS windows WORKDIR /app COPY --from=windows-builder /build/kapinger.exe . ENTRYPOINT [ "cmd.exe" ] diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 475de1a33e..e321afcc13 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,10 +1,11 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:66a04c4bcea1fafc935246c96af236eb4d91d501387e061ae59f134c8993dae9 AS build +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . -FROM mcr.microsoft.com/mirror/docker/library/ubuntu:24.04 +# skopeo inspect docker://mcr.microsoft.com/mirror/docker/library/ubuntu:24.04 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/mirror/docker/library/ubuntu@sha256:c35e29c9450151419d9448b0fd75374fec4fff364a27f176fb458d472dfc9e54 RUN apt-get update RUN apt-get install -y \ axel \ diff --git a/operator/Dockerfile b/operator/Dockerfile index a6e34f5037..2465dcf6bc 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,7 +25,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ ##################### controller ####################### # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:c9a1ed9515e033bca0c0b3171eccec41790bfcb9e47f05130cddc0a458de46ba +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 0b47c88f7a..2a3e392aaf 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder # Build args ARG VERSION @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:60612a30303eb5a15ce7f53fa2eecf70bca41d72657de0482fbde601ae5f3403 +FROM mcr.microsoft.com/windows/nanoserver@sha256:be41510eb214c55def9162ef1fb5e71f1b71ce4d64d91bc963199f2383e034ea COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/scripts/bump-images.sh b/scripts/bump-images.sh new file mode 100755 index 0000000000..7e79753b31 --- /dev/null +++ b/scripts/bump-images.sh @@ -0,0 +1,191 @@ +#!/usr/bin/env bash +# bump-images.sh — update all Dockerfile base image digests. +# +# Parses "# skopeo inspect docker://IMAGE:TAG ..." comments in Dockerfiles +# and replaces the sha256 digest on the following FROM line with the latest +# digest from the registry. Supports --override-os windows for Windows images. +# +# For Go builder images (golang), also checks for newer minor/patch versions +# and prompts the user to select a version before updating digests. +# +# Usage: make bump-images +# Requires: skopeo, curl, python3 + +set -euo pipefail + +if ! command -v skopeo &>/dev/null; then + echo "error: skopeo is required but not installed" >&2 + exit 1 +fi + +REPO_ROOT="$(git rev-parse --show-toplevel)" +DOCKERFILES=$(find "$REPO_ROOT" -name "Dockerfile*" -not -path "*/.git/*" -not -path "*/vendor/*") + +# --- Go version bump detection --- +# Scan Dockerfiles for Go builder images and check for newer versions. + +go_image_repo="" +current_go_version="" + +for dockerfile in $DOCKERFILES; do + if match=$(grep -oP 'docker://\S+/golang:\K[0-9]+\.[0-9]+\.[0-9]+' "$dockerfile" | head -1); then + if [[ -n "$match" ]]; then + current_go_version="$match" + go_image_repo=$(grep -oP 'docker://\K\S+/golang(?=:)' "$dockerfile" | head -1) + break + fi + fi +done + +if [[ -n "$current_go_version" && -n "$go_image_repo" ]]; then + echo "Current Go builder version: $current_go_version ($go_image_repo)" + + # Parse current version components + IFS='.' read -r cur_major cur_minor cur_patch <<< "$current_go_version" + + # Fetch available tags from MCR API + # Convert image repo to registry API path (mcr.microsoft.com/foo/bar → /v2/foo/bar/tags/list) + registry_host=$(echo "$go_image_repo" | cut -d/ -f1) + repo_path=$(echo "$go_image_repo" | cut -d/ -f2-) + tags_json=$(curl -s "https://${registry_host}/v2/${repo_path}/tags/list" 2>/dev/null || true) + + if [[ -n "$tags_json" ]]; then + # Extract unique Go versions (MAJOR.MINOR.PATCH only, no suffix) that are newer + newer_versions=$(echo "$tags_json" | python3 -c " +import sys, json + +data = json.load(sys.stdin) +tags = data.get('tags', []) + +cur_major, cur_minor, cur_patch = ${cur_major}, ${cur_minor}, ${cur_patch} +seen = set() +results = [] + +for tag in tags: + # Match tags that are exactly MAJOR.MINOR.PATCH (no suffix) + parts = tag.split('.') + if len(parts) != 3: + continue + try: + major, minor, patch = int(parts[0]), int(parts[1]), int(parts[2]) + except ValueError: + continue + + version = (major, minor, patch) + if version in seen: + continue + seen.add(version) + + # Only include versions newer than current, same major + if major != cur_major: + continue + if (minor, patch) <= (cur_minor, cur_patch): + continue + results.append(version) + +for v in sorted(results): + kind = 'minor' if v[1] > cur_minor else 'patch' + print(f'{v[0]}.{v[1]}.{v[2]} ({kind})') +" 2>/dev/null || true) + + if [[ -n "$newer_versions" ]]; then + echo "" + echo "Newer Go versions available:" + i=1 + versions_array=() + while IFS= read -r line; do + echo " $i) $line" + # Extract just the version number (before the space) + versions_array+=("${line%% *}") + ((i++)) + done <<< "$newer_versions" + echo " 0) Keep current ($current_go_version)" + echo "" + + if [[ -t 0 ]]; then + read -r -p "Select version to bump to [0]: " choice + else + echo "Non-interactive mode, keeping current version." + choice=0 + fi + choice="${choice:-0}" + + if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#versions_array[@]} )); then + new_go_version="${versions_array[$((choice - 1))]}" + echo "" + echo "Bumping Go version: $current_go_version → $new_go_version" + + # Update all Dockerfiles: replace old Go version with new in golang image tags + for dockerfile in $DOCKERFILES; do + # Update skopeo comment lines and FROM lines referencing the golang image + if grep -q "golang:${current_go_version}" "$dockerfile"; then + sed -i "s|golang:${current_go_version}|golang:${new_go_version}|g" "$dockerfile" + rel_path="${dockerfile#$REPO_ROOT/}" + echo " GO $rel_path: ${current_go_version} → ${new_go_version}" + fi + done + echo "" + else + echo "Keeping Go version at $current_go_version." + echo "" + fi + else + echo "No newer Go versions found." + echo "" + fi + fi +fi + +# --- Digest bump loop --- + +updated=0 +skipped=0 + +for dockerfile in $DOCKERFILES; do + # Find all skopeo comment lines + while IFS= read -r line_num; do + # Extract the skopeo command from the comment + comment=$(sed -n "${line_num}p" "$dockerfile") + + # Parse image reference from: # skopeo inspect docker://IMAGE:TAG [--override-os windows] ... + image_ref=$(echo "$comment" | grep -oP 'docker://\S+' | sed 's/docker:\/\///') + override_os=$(echo "$comment" | grep -oP '\-\-override-os \S+' || true) + + if [[ -z "$image_ref" ]]; then + continue + fi + + # Get current digest from the FROM line (next non-empty line after comment) + from_line=$((line_num + 1)) + current=$(sed -n "${from_line}p" "$dockerfile" | grep -oP 'sha256:[a-f0-9]+' || true) + + if [[ -z "$current" ]]; then + continue + fi + + # Fetch latest digest + latest=$(skopeo inspect "docker://${image_ref}" $override_os --format "{{.Digest}}" 2>/dev/null || true) + + if [[ -z "$latest" ]]; then + echo "SKIP $image_ref (inspect failed)" >&2 + ((skipped++)) || true + continue + fi + + if [[ "$current" == "$latest" ]]; then + ((skipped++)) || true + continue + fi + + # Replace old digest with new in the entire file (handles multi-use of same digest) + sed -i "s|${current}|${latest}|g" "$dockerfile" + rel_path="${dockerfile#$REPO_ROOT/}" + echo "BUMP $rel_path: $image_ref" + echo " ${current:0:19}... → ${latest:0:19}..." + ((updated++)) || true + + done < <(grep -n "skopeo inspect" "$dockerfile" | cut -d: -f1) +done + +echo "" +echo "Done: $updated updated, $skipped unchanged" diff --git a/shell/Dockerfile b/shell/Dockerfile index 86f6605055..65070649a1 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:2a97a634da103fbfc21697f0136231f17ad18f7880a5be94488c5d2b15eb02d3 +FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 RUN tdnf install -y \ bind-utils \ diff --git a/test/image/Dockerfile b/test/image/Dockerfile index f9552e56e4..3dbcd13fa8 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.0-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:0a0df8a0d91137926313f5eaa77de14edb89254cef8ef4a07208e1119c6067ef AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From f913e798b3dd2b4c2d93fb0699e38ebc529eb76c Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Tue, 7 Apr 2026 11:12:57 +0100 Subject: [PATCH 291/448] fix: Pod IP Deletion Leak in eBPF FilterMap (#2114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fix: Pod IP Deletion Leak in eBPF FilterMap ## Problem Pod IPs accumulate indefinitely in the eBPF filtermap because DELETE operations fail in two ways: 1. **`PodCallBackFn` guard drops delete events**: When a namespace is removed from the include list or a pod annotation is removed, `nsOfInterest()` and `podOfInterest()` both return false — the `PodDeleted` event is silently discarded before reaching `handlePodEvent()`. 2. **`applyDirtyPodsDelete` uses wrong metadata**: Even if the event reaches the delete path, `Annotated` and `Namespaced` flags are re-evaluated at delete time against current state (not the state when the IP was added). The filtermanager requires matching `(Requestor, RequestMetadata)` to remove a reference — a delete with the wrong metadata is a no-op. This causes "no space left on device" errors when the eBPF filtermap fills up (255 entries). Please provide a brief description of the changes made in this pull request. ## Fix **Two changes in `pkg/module/metrics/metrics_module.go`:** 1. **Bypass guard for `PodDeleted` events** — `PodCallBackFn` now skips the `nsOfInterest`/`podOfInterest` check when `event.Type == EventTypePodDeleted`, ensuring delete events always reach `handlePodEvent`. 2. **Always delete with both metadata types** — `applyDirtyPodsDelete` unconditionally issues `DeleteIPs` with both `modulePodReqMetadata` ("pod") and `moduleReqMetadata` ("namespace") for every IP in the delete list. The filtermanager's `deleteIP` is a safe no-op when the metadata doesn't exist for an IP, so extra calls cause no harm. **Additional minor fix:** Replaced `zap.Any` with `fmt.Sprint` for `[]net.IP` log fields to fix `unsupported value type` errors in log output. ## Tests Unit tests added and manual test done. ### Manual validation #### Scenario 1 — Namespace filter change (annotations mode) Test: ```bash helm install with: enableAnnotations=true, enablePodLevel=true kubectl create namespace test-leak-ns kubectl run test-pod -n test-leak-ns --image=nginx kubectl annotate namespace test-leak-ns retina.sh=observe # → Verify: "Adding IPs to filter manager" with pod IP in retina logs kubectl annotate namespace test-leak-ns retina.sh- kubectl delete pod test-pod -n test-leak-ns # → Verify: "Adding pod IP to DELETE dirty pods cache" and "Deleting Ips in dirty pods from filtermap" in retina logs ``` Logs: ```bash === ADD phase === Defaulted container "retina" out of: retina, init-retina (init) ts=2026-03-16T10:30:44.504Z level=info caller=metrics/metrics_module.go:391 msg="Namespaces to add" namespaces= ts=2026-03-16T10:30:44.504Z level=info caller=metrics/metrics_module.go:391 msg="Namespaces to add" namespaces=test-leak-ns ts=2026-03-16T10:30:44.504Z level=info caller=metrics/metrics_module.go:397 msg="Adding IPs to filter manager" namespace=test-leak-ns ips=[10.224.0.32] namespace/test-leak-ns annotated pod "test-pod" deleted === DELETE phase === Defaulted container "retina" out of: retina, init-retina (init) ts=2026-03-16T10:31:12.955Z level=info caller=metrics/metrics_module.go:478 msg="Adding pod IP to DELETE dirty pods cache" pod name=test-leak-ns/test-pod ts=2026-03-16T10:31:13.504Z level=debug caller=metrics/metrics_module.go:544 msg="Deleting Ips in dirty pods from filtermap" IPs=[10.224.0.32] ``` #### Scenario 2 — Namespace filter change (MetricsConfiguration CRD mode) Test: ```bash helm install with: enableAnnotations=false, enablePodLevel=true kubectl create namespace test-leak-ns kubectl run test-pod -n test-leak-ns --image=nginx Apply MetricsConfiguration CRD with namespaces.include: [test-leak-ns] # → Verify: "Adding IPs to filter manager" with pod IP in retina logs Update MetricsConfiguration CRD to namespaces.include: [default] kubectl delete pod test-pod -n test-leak-ns # → Verify: "Adding pod IP to DELETE dirty pods cache" and "Deleting Ips in dirty pods from filtermap" in retina logs ``` Logs: ```bash === ADD phase === Defaulted container "retina" out of: retina, init-retina (init) ts=2026-03-16T10:37:22.462Z level=info caller=metrics/metrics_module.go:158 msg="Reconciling metric module" spec= specError="unsupported value type" ts=2026-03-16T10:37:22.462Z level=info caller=metrics/metrics_module.go:391 msg="Namespaces to add" namespaces= ts=2026-03-16T10:37:22.462Z level=info caller=metrics/metrics_module.go:391 msg="Namespaces to add" namespaces=test-leak-ns ts=2026-03-16T10:37:22.463Z level=info caller=metrics/metrics_module.go:397 msg="Adding IPs to filter manager" namespace=test-leak-ns ips=[10.224.0.36] metricsconfiguration.retina.sh/test-metricsconfig configured pod "test-pod" deleted === DELETE phase === Defaulted container "retina" out of: retina, init-retina (init) ts=2026-03-16T10:37:49.138Z level=info caller=metrics/metrics_module.go:478 msg="Adding pod IP to DELETE dirty pods cache" pod name=test-leak-ns/test-pod ts=2026-03-16T10:37:49.465Z level=debug caller=metrics/metrics_module.go:544 msg="Deleting Ips in dirty pods from filtermap" IPs=[10.224.0.36] metricsconfiguration.retina.sh "test-metricsconfig" deleted namespace "test-leak-ns" deleted ``` #### Scenario 3 — Pod annotation removed then deleted Test: ```bash helm install with: enableAnnotations=true, enablePodLevel=true Create pod with annotation retina.sh=observe in default namespace # → Verify: "Adding pod IP to ADD dirty pods cache" in retina logs kubectl annotate pod annotated-pod -n default retina.sh- kubectl delete pod annotated-pod -n default # → Verify: "Adding pod IP to DELETE dirty pods cache" and "Deleting Ips in dirty pods from filtermap" in retina logs ``` Logs: ```bash === ADD phase === Defaulted container "retina" out of: retina, init-retina (init) ts=2026-03-16T10:32:59.294Z level=info caller=metrics/metrics_module.go:475 msg="Adding pod IP to ADD dirty pods cache" pod name=default/annotated-pod ts=2026-03-16T10:32:59.504Z level=debug caller=metrics/metrics_module.go:515 msg="Adding annotated pod IPs to filtermap" IPs=[10.224.0.31] pod/annotated-pod annotated pod "annotated-pod" deleted === DELETE phase === Defaulted container "retina" out of: retina, init-retina (init) ts=2026-03-16T10:33:14.229Z level=info caller=metrics/metrics_module.go:470 msg="Adding pod IP to DELETE dirty pods cache. Pod not annotated or in namespace of interest." pod name=default/annotated-pod ts=2026-03-16T10:33:14.505Z level=debug caller=metrics/metrics_module.go:544 msg="Deleting Ips in dirty pods from filtermap" IPs=[10.224.0.31] ``` ## Related Issue #2085 ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Alex Castilio dos Santos Co-authored-by: Iti Agrawal --- pkg/module/metrics/metrics_module.go | 78 ++-- .../metrics/metrics_module_linux_test.go | 435 ++++++++++++++++++ 2 files changed, 479 insertions(+), 34 deletions(-) diff --git a/pkg/module/metrics/metrics_module.go b/pkg/module/metrics/metrics_module.go index 78b771efe0..6d473f1d49 100644 --- a/pkg/module/metrics/metrics_module.go +++ b/pkg/module/metrics/metrics_module.go @@ -4,6 +4,7 @@ package metrics import ( "context" + "fmt" "net" "strings" "sync" @@ -385,7 +386,7 @@ func (m *Module) appendIncludeList(namespaces []string) { // toAdd namespace IPs to filter manager for _, ns := range toAdd { ips := m.daemonCache.GetIPsByNamespace(ns) - m.l.Info("Adding IPs to filter manager", zap.String("namespace", ns), zap.Any("ips", ips)) + m.l.Info("Adding IPs to filter manager", zap.String("namespace", ns), zap.String("ips", fmt.Sprint(ips))) err := m.filterManager.AddIPs(ips, metricModuleReq, moduleReqMetadata) if err != nil { @@ -396,7 +397,7 @@ func (m *Module) appendIncludeList(namespaces []string) { // toRemove namespace IPs from filter manager for _, ns := range toRemove { ips := m.daemonCache.GetIPsByNamespace(ns) - m.l.Info("Removing IPs from filter manager", zap.String("namespace", ns), zap.Any("ips", ips)) + m.l.Info("Removing IPs from filter manager", zap.String("namespace", ns), zap.String("ips", fmt.Sprint(ips))) err := m.filterManager.DeleteIPs(ips, metricModuleReq, moduleReqMetadata) if err != nil { @@ -495,25 +496,32 @@ func (m *Module) PodCallBackFn(obj interface{}) { return } - m.Lock() - if !m.nsOfInterest(pod.Namespace()) && !m.podOfInterest(ip, pod.Annotations()) { - m.Unlock() + // Compute interest flags under RLock so we don't race with Reconcile/appendIncludeList + // which mutate the namespace maps under Lock. + m.RLock() + annotated := m.podAnnotated(pod.Annotations()) + namespaced := m.nsOfInterest(pod.Namespace()) + m.RUnlock() + + if event.Type != cache.EventTypePodDeleted && !namespaced && !m.filterManager.HasIP(ip) && !annotated { return } - m.Unlock() - handlePodEvent(event, m, pod, ip) + handlePodEvent(event, m, pod, ip, annotated, namespaced) } -func handlePodEvent(event *cache.CacheEvent, m *Module, pod *common.RetinaEndpoint, ip net.IP) { +func handlePodEvent( + event *cache.CacheEvent, m *Module, pod *common.RetinaEndpoint, + ip net.IP, annotated, namespaced bool, +) { if pod.Name() == common.APIServerEndpointName && pod.Namespace() == common.APIServerEndpointName { m.l.Debug("Ignoring apiserver endpoint") return } podCacheEntry := DirtyCachePod{ IP: ip, - Annotated: m.podAnnotated(pod.Annotations()), - Namespaced: m.nsOfInterest(pod.Namespace()), + Annotated: annotated, + Namespaced: namespaced, } switch event.Type { case cache.EventTypePodAdded: @@ -522,13 +530,24 @@ func handlePodEvent(event *cache.CacheEvent, m *Module, pod *common.RetinaEndpoi // This case should only occur when the pod annotation is removed since this is an EventTypePodAdded (also accounts for pod update) if !podCacheEntry.Annotated && !podCacheEntry.Namespaced { m.l.Info("Adding pod IP to DELETE dirty pods cache. Pod not annotated or in namespace of interest.", zap.String("pod name", pod.NamespacedName())) - podCacheEntry.Annotated = true m.dirtyPods.ToDelete(ip.String(), podCacheEntry) return } m.l.Info("Adding pod IP to ADD dirty pods cache", zap.String("pod name", pod.NamespacedName())) m.dirtyPods.ToAdd(podCacheEntry.IP.String(), podCacheEntry) case cache.EventTypePodDeleted: + // Guard against spurious DELETE events during pod churn / IP reuse. + // The cache (pkg/controllers/cache/cache.go) updates its maps synchronously + // (epMap/ipToEpKey) and then publishes events asynchronously via a goroutine. + // So when we process this DELETE, if a new pod already reused the IP, the + // cache will still contain a valid entry. Deleting would incorrectly remove it. + if endpoint := m.daemonCache.GetPodByIP(ip.String()); endpoint != nil { + m.l.Debug("Ignoring DELETE for reused IP — pod still exists in cache", + zap.String("deleted pod", pod.NamespacedName()), + zap.String("ip", ip.String()), + zap.String("cached pod", endpoint.NamespacedName())) + return + } m.l.Info("Adding pod IP to DELETE dirty pods cache", zap.String("pod name", pod.NamespacedName())) m.dirtyPods.ToDelete(ip.String(), podCacheEntry) default: @@ -566,14 +585,14 @@ func (m *Module) applyDirtyPodsAdd() { } } if len(podsToAdd) > 0 { - m.l.Debug("Adding annotated pod IPs to filtermap", zap.Any("IPs", podsToAdd)) + m.l.Debug("Adding annotated pod IPs to filtermap", zap.String("IPs", fmt.Sprint(podsToAdd))) err := m.filterManager.AddIPs(podsToAdd, metricModuleReq, modulePodReqMetadata) if err != nil { m.l.Error("Error adding pod IP to filter manager", zap.Error(err)) } } if len(podsToAddNamespaced) > 0 { - m.l.Debug("Adding namespaced pod IPs to filtermap", zap.Any("IPs", podsToAddNamespaced)) + m.l.Debug("Adding namespaced pod IPs to filtermap", zap.String("IPs", fmt.Sprint(podsToAddNamespaced))) err := m.filterManager.AddIPs(podsToAddNamespaced, metricModuleReq, moduleReqMetadata) if err != nil { m.l.Error("Error adding pod IP to filter manager", zap.Error(err)) @@ -583,35 +602,26 @@ func (m *Module) applyDirtyPodsAdd() { m.dirtyPods.ClearAdd() } -// applyDirtyPodsDelete deletes pod ips from filtermanager +// applyDirtyPodsDelete deletes pod ips from filtermanager. +// Always attempts deletion with both metadata types (pod and namespace). +// The filtermanager cache makes extra deletes a safe no-op when the metadata doesn't exist. func (m *Module) applyDirtyPodsDelete() { deletes := m.dirtyPods.GetDeleteList() if len(deletes) > 0 { - podOfInterestDeleteList := make([]net.IP, 0) - namespaceOfInterestDeleteList := make([]net.IP, 0) + ipsToDelete := make([]net.IP, 0, len(deletes)) for _, entry := range deletes { podEntry := entry.(DirtyCachePod) - if podEntry.Annotated { - podOfInterestDeleteList = append(podOfInterestDeleteList, podEntry.IP) - } - if podEntry.Namespaced { - namespaceOfInterestDeleteList = append(namespaceOfInterestDeleteList, podEntry.IP) - } + ipsToDelete = append(ipsToDelete, podEntry.IP) } - if len(podOfInterestDeleteList) > 0 { - m.l.Debug("Deleting Ips in dirty pods from filtermap", zap.Any("IPs", podOfInterestDeleteList)) - err := m.filterManager.DeleteIPs(podOfInterestDeleteList, metricModuleReq, modulePodReqMetadata) - if err != nil { - m.l.Error("Error deleting pod IP from filter manager", zap.Error(err)) - } + m.l.Debug("Deleting Ips in dirty pods from filtermap", zap.String("IPs", fmt.Sprint(ipsToDelete))) + err := m.filterManager.DeleteIPs(ipsToDelete, metricModuleReq, modulePodReqMetadata) + if err != nil { + m.l.Error("Error deleting pod IP from filter manager", zap.Error(err)) } - if len(namespaceOfInterestDeleteList) > 0 { - m.l.Debug("Deleting Ips in dirty pods from filtermap", zap.Any("IPs", namespaceOfInterestDeleteList)) - err := m.filterManager.DeleteIPs(namespaceOfInterestDeleteList, metricModuleReq, moduleReqMetadata) - if err != nil { - m.l.Error("Error deleting pod IP from filter manager", zap.Error(err)) - } + err = m.filterManager.DeleteIPs(ipsToDelete, metricModuleReq, moduleReqMetadata) + if err != nil { + m.l.Error("Error deleting pod IP from filter manager", zap.Error(err)) } } diff --git a/pkg/module/metrics/metrics_module_linux_test.go b/pkg/module/metrics/metrics_module_linux_test.go index abc37b5552..faca72d199 100644 --- a/pkg/module/metrics/metrics_module_linux_test.go +++ b/pkg/module/metrics/metrics_module_linux_test.go @@ -259,6 +259,7 @@ func TestPodCallBack(t *testing.T) { fm := filtermanager.NewMockIFilterManager(ctrl) //nolint:typecheck c := cache.NewMockCacheInterface(ctrl) //nolint:typecheck c.EXPECT().GetIPsByNamespace(gomock.Any()).Return([]net.IP{}).AnyTimes() + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() fm.EXPECT().AddIPs([]net.IP{}, gomock.Any(), gomock.Any()).Return(nil).Times(1) fm.EXPECT().HasIP(gomock.Any()).Return(tt.fmHasIP).AnyTimes() if len(tt.addExpected) > 0 { @@ -912,3 +913,437 @@ func TestPodCallBackExclude(t *testing.T) { adds = me.dirtyPods.GetAddList() assert.Len(t, adds, 1, "pod in excluded namespace should not be added to dirty pods") } + +func TestDeletePodAfterNamespaceRemoved(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = false + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + ip1 := net.IPv4(10, 0, 0, 1) + + // appendIncludeList(["ns1"]) will add namespace IPs + c.EXPECT().GetIPsByNamespace("ns1").Return([]net.IP{}).Times(1) + fm.EXPECT().AddIPs([]net.IP{}, gomock.Any(), gomock.Any()).Return(nil).Times(1) + // PodAdded: add with namespace metadata + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // appendIncludeList([]) removes ns1 + c.EXPECT().GetIPsByNamespace("ns1").Return([]net.IP{ip1}).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // PodDeleted: applyDirtyPodsDelete should attempt both metadata types + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // Pod is genuinely deleted — GetPodByIP returns nil + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + // Add pod in tracked namespace + me.appendIncludeList([]string{"ns1"}) + pod1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + me.applyDirtyPods() + + // Remove namespace from include list + me.appendIncludeList([]string{}) + + // Delete pod — ns no longer of interest + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1)) + me.applyDirtyPods() +} + +func TestDeletePodAfterAnnotationRemovedDirectDelete(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = true + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + ip1 := net.IPv4(10, 0, 0, 1) + + // PodAdded: add with pod metadata (annotated, ns not of interest) + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + // PodDeleted: applyDirtyPodsDelete should attempt both metadata types + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // Pod is genuinely deleted — GetPodByIP returns nil + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + // Add annotated pod + pod1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + pod1.SetAnnotations(map[string]string{common.RetinaPodAnnotation: common.RetinaPodAnnotationValue}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + me.applyDirtyPods() + + // Delete pod with annotation already removed (no intermediate update event) + pod1NoAnnotation := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1NoAnnotation)) + me.applyDirtyPods() +} + +func TestDeletePodTrackedByBothAfterNamespaceRemoved(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = true + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + ip1 := net.IPv4(10, 0, 0, 1) + + // appendIncludeList(["ns1"]) initial setup + c.EXPECT().GetIPsByNamespace("ns1").Return([]net.IP{}).Times(1) + fm.EXPECT().AddIPs([]net.IP{}, gomock.Any(), gomock.Any()).Return(nil).Times(1) + // PodAdded: add with both metadata types (annotated + namespaced) + fm.EXPECT().HasIP(gomock.Any()).Return(true).AnyTimes() + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // appendIncludeList([]) removes ns1 + c.EXPECT().GetIPsByNamespace("ns1").Return([]net.IP{ip1}).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // PodDeleted: applyDirtyPodsDelete should attempt both metadata types + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // Pod is genuinely deleted — GetPodByIP returns nil + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + // Add annotated pod in tracked namespace + me.appendIncludeList([]string{"ns1"}) + pod1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + pod1.SetAnnotations(map[string]string{common.RetinaPodAnnotation: common.RetinaPodAnnotationValue}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + me.applyDirtyPods() + + // Remove namespace from include list + me.appendIncludeList([]string{}) + + // Delete pod — annotation still present but ns no longer of interest + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1)) + me.applyDirtyPods() +} + +func TestDeletePodNeverTracked(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = false + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + fm.EXPECT().DeleteIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + // Pod is genuinely deleted — GetPodByIP returns nil + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + includedNamespaces: map[string]struct{}{"ns1": {}}, + } + + // Delete a pod in ns2 (not tracked, never added) + pod1 := common.NewRetinaEndpoint("pod1", "ns2", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 1)}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1)) + me.applyDirtyPods() +} + +func TestNormalPodLifecycleInTrackedNamespace(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = false + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + ip1 := net.IPv4(10, 0, 0, 1) + + c.EXPECT().GetIPsByNamespace("ns1").Return([]net.IP{}).Times(1) + fm.EXPECT().AddIPs([]net.IP{}, gomock.Any(), gomock.Any()).Return(nil).Times(1) + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + // Allow the extra modulePodReqMetadata delete (no-op) after fix + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).AnyTimes() + // Pod is genuinely deleted — GetPodByIP returns nil + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + me.appendIncludeList([]string{"ns1"}) + pod1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + me.applyDirtyPods() + + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1)) + me.applyDirtyPods() +} + +func TestAnnotatedPodNormalLifecycle(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = true + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + ip1 := net.IPv4(10, 0, 0, 1) + + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), modulePodReqMetadata).Return(nil).Times(1) + // Allow the extra moduleReqMetadata delete (no-op) after fix + fm.EXPECT().DeleteIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).AnyTimes() + // Pod is genuinely deleted — GetPodByIP returns nil + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + pod1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + pod1.SetAnnotations(map[string]string{common.RetinaPodAnnotation: common.RetinaPodAnnotationValue}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + me.applyDirtyPods() + + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1)) + me.applyDirtyPods() +} + +// TestSpuriousDeleteIPReuse verifies that a DELETE event is ignored when the +// daemon cache still contains a pod at the same IP (IP reuse by a new pod). +func TestSpuriousDeleteIPReuse(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = false + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + ip1 := net.IPv4(10, 0, 0, 1) + + // Setup tracked namespace + c.EXPECT().GetIPsByNamespace("ns1").Return([]net.IP{}).Times(1) + fm.EXPECT().AddIPs([]net.IP{}, gomock.Any(), gomock.Any()).Return(nil).Times(1) + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + fm.EXPECT().AddIPs([]net.IP{ip1}, gomock.Any(), moduleReqMetadata).Return(nil).Times(1) + + // Pod still exists in daemon cache (IP reused) — GetPodByIP returns a valid endpoint. + // No DeleteIPs calls should occur because the DELETE event is skipped. + newPod := common.NewRetinaEndpoint("pod2", "ns1", &common.IPAddresses{IPv4: ip1}) + c.EXPECT().GetPodByIP(ip1.String()).Return(newPod).Times(1) + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + me.appendIncludeList([]string{"ns1"}) + + // Add original pod + pod1 := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: ip1}) + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod1)) + me.applyDirtyPods() + + // Simulate spurious DELETE — daemon cache already has pod2 at the same IP. + // The DELETE should be ignored; dirty pods delete list should remain empty. + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodDeleted, pod1)) + me.applyDirtyPods() // No DeleteIPs expected +} + +// TestPodCallBackConcurrentWithReconcile verifies that PodCallBackFn (which reads +// namespace maps under RLock) does not race with appendIncludeList (which mutates +// them under Lock). Run with -race to detect data races. +func TestPodCallBackConcurrentWithReconcile(t *testing.T) { + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cfg, _ := kcfg.GetConfig(testCfgFile) + cfg.EnableAnnotations = true + + p := pubsub.NewMockPubSubInterface(ctrl) + e := enricher.NewMockEnricherInterface(ctrl) + fm := filtermanager.NewMockIFilterManager(ctrl) + c := cache.NewMockCacheInterface(ctrl) + + c.EXPECT().GetIPsByNamespace(gomock.Any()).Return([]net.IP{}).AnyTimes() + fm.EXPECT().AddIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + fm.EXPECT().DeleteIPs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + fm.EXPECT().HasIP(gomock.Any()).Return(false).AnyTimes() + c.EXPECT().GetPodByIP(gomock.Any()).Return(nil).AnyTimes() + + me := &Module{ + RWMutex: &sync.RWMutex{}, + l: log.Logger().Named("MetricModule"), + pubsub: p, + configs: make([]*api.MetricsConfiguration, 0), + enricher: e, + wg: sync.WaitGroup{}, + registry: make(map[string]AdvMetricsInterface), + moduleCtx: context.Background(), + filterManager: fm, + daemonCache: c, + dirtyPods: common.NewDirtyCache(), + pubsubPodSub: "", + daemonConfig: cfg, + } + + me.appendIncludeList([]string{"ns1"}) + + pod := common.NewRetinaEndpoint("pod1", "ns1", &common.IPAddresses{IPv4: net.IPv4(10, 0, 0, 1)}) + pod.SetAnnotations(map[string]string{common.RetinaPodAnnotation: common.RetinaPodAnnotationValue}) + + // Run PodCallBackFn and appendIncludeList concurrently. + // With -race this will catch any unprotected map access. + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + for i := 0; i < 100; i++ { + me.PodCallBackFn(cache.NewCacheEvent(cache.EventTypePodAdded, pod)) + } + }() + go func() { + defer wg.Done() + for i := 0; i < 100; i++ { + me.Lock() + me.appendIncludeList([]string{"ns1", "ns2"}) + me.Unlock() + } + }() + wg.Wait() +} From c08d827340f1401fe915438aba4635f018dc716f Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:56:08 +0200 Subject: [PATCH 292/448] chore(security): mitigate CVEs in dependencies and build toolchain (#2159) # Description This PR mitigates the non-cilium CVEs reported for `mcr.microsoft.com/containernetworking/retina-agent:v1.0.3` by updating vulnerable Go dependencies and refreshing pinned Go toolchain image digests used in builds. ## What changed - Updated `google.golang.org/grpc` to `v1.80.0`. - Updated `github.com/docker/docker` to `v28.5.2+incompatible`. - Updated `go.sum` to reflect the new dependency graph. - Refreshed pinned Go builder image digests across build Dockerfiles to pick up stdlib/toolchain security fixes. ## CVEs mitigated in this commit ### gRPC - CVE-2026-33186 ### Docker - CVE-2026-33997 - CVE-2026-34040 ### Go stdlib / toolchain - CVE-2025-61726 - CVE-2025-61727 - CVE-2025-61728 - CVE-2025-61729 - CVE-2025-61730 - CVE-2025-68121 - CVE-2026-25679 - CVE-2026-27139 - CVE-2026-27142 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/Dockerfile | 4 +- controller/Dockerfile | 4 +- controller/Dockerfile.gogen | 4 +- controller/Dockerfile.proto | 4 +- controller/Dockerfile.windows-cgo | 4 +- controller/Dockerfile.windows-native | 4 +- go.mod | 56 ++++++------ go.sum | 124 +++++++++++++-------------- hack/tools/kapinger/Dockerfile | 8 +- hack/tools/toolbox/Dockerfile | 4 +- operator/Dockerfile | 4 +- operator/Dockerfile.windows-2022 | 4 +- test/image/Dockerfile | 4 +- 13 files changed, 114 insertions(+), 114 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index ad7042741c..170e9b941a 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index a56591d69b..1845cd40a4 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 9dbf6616e4..4b7b32da2e 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 9f19d9eced..1d3742b774 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 85a65f2236..6ceebc2e40 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:a6a40696becc6eae6a673f037349bbdccd4420cccd5c6f9336c71581c1395407 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index c0e3e99513..e7d33fdb98 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:a6a40696becc6eae6a673f037349bbdccd4420cccd5c6f9336c71581c1395407 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/go.mod b/go.mod index 2552fc6360..5d90fb10f7 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ retract ( ) require ( - cel.dev/expr v0.24.0 // indirect + cel.dev/expr v0.25.1 // indirect code.cloudfoundry.org/clock v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect @@ -67,7 +67,7 @@ require ( github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a // indirect github.com/cilium/lumberjack/v2 v2.4.1 // indirect github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect - github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect + github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/containerd v1.7.29 // indirect github.com/containerd/continuity v0.4.4 // indirect @@ -84,14 +84,14 @@ require ( github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v26.0.0+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v28.0.4+incompatible // indirect + github.com/docker/docker v28.5.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect - github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/evanphx/json-patch v5.9.11+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect @@ -159,7 +159,7 @@ require ( github.com/moby/moby v26.1.0+incompatible // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/mountinfo v0.7.1 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/signal v0.7.0 // indirect github.com/moby/sys/user v0.3.0 // indirect github.com/moby/term v0.5.0 // indirect @@ -187,7 +187,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/spiffe/spire-api-sdk v1.12.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect @@ -200,7 +200,6 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect - github.com/zeebo/errs v1.4.0 // indirect go.etcd.io/etcd/api/v3 v3.5.21 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect go.etcd.io/etcd/client/v3 v3.5.21 // indirect @@ -209,15 +208,15 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/mod v0.30.0 - golang.org/x/text v0.32.0 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/mod v0.31.0 + golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.39.0 // indirect + golang.org/x/tools v0.40.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/apiserver v0.32.3 // indirect k8s.io/component-base v0.32.3 // indirect @@ -240,11 +239,11 @@ require ( github.com/spf13/pflag v1.0.9 github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.48.0 // indirect + golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/sync v0.19.0 - golang.org/x/sys v0.39.0 - golang.org/x/term v0.38.0 // indirect + golang.org/x/sys v0.40.0 + golang.org/x/term v0.39.0 // indirect google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 @@ -302,12 +301,12 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 - go.opentelemetry.io/otel v1.37.0 - go.opentelemetry.io/otel/metric v1.37.0 - go.opentelemetry.io/otel/trace v1.37.0 + go.opentelemetry.io/otel v1.39.0 + go.opentelemetry.io/otel/metric v1.39.0 + go.opentelemetry.io/otel/trace v1.39.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - google.golang.org/grpc v1.75.1 + google.golang.org/grpc v1.80.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 @@ -326,7 +325,7 @@ require ( github.com/containerd/containerd/api v1.8.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/google/cel-go v0.24.1 // indirect github.com/moby/sys/userns v0.1.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect @@ -338,7 +337,7 @@ require ( cloud.google.com/go v0.116.0 // indirect cloud.google.com/go/auth v0.15.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect - cloud.google.com/go/compute/metadata v0.7.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/kms v1.20.1 // indirect cloud.google.com/go/longrunning v0.6.2 // indirect @@ -365,7 +364,7 @@ require ( github.com/Crocmagnon/fatcontext v0.7.1 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect @@ -436,7 +435,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.5 // indirect @@ -541,6 +540,7 @@ require ( github.com/mgechev/revive v1.7.0 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/sys/atomicwriter v0.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect @@ -630,14 +630,14 @@ require ( gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect go-simpler.org/musttag v0.13.0 // indirect go-simpler.org/sloglint v0.9.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.37.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect + go.opentelemetry.io/otel/sdk v1.39.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.39.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect diff --git a/go.sum b/go.sum index 50dcee13ba..dc79055af5 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ 4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= -cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= -cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= @@ -12,8 +12,8 @@ cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= -cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= -cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= cloud.google.com/go/kms v1.20.1 h1:og29Wv59uf2FVaZlesaiDAqHFzHaoUyHI3HYp9VUHVg= @@ -163,8 +163,8 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rW github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= @@ -411,8 +411,8 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= -github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -488,8 +488,8 @@ github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUy github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok= -github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +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/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -517,15 +517,15 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= -github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= -github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= -github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= +github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= -github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= +github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= @@ -595,8 +595,8 @@ github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -1100,10 +1100,12 @@ github.com/moby/moby v26.1.0+incompatible h1:mjepCwMH0KpCgPvrXjqqyCeTCHgzO7p9TwZ github.com/moby/moby v26.1.0+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +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/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +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/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= @@ -1373,8 +1375,8 @@ github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= -github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/spiffe/spire-api-sdk v1.12.0 h1:xx6PAsoBTvMtNe7h5dGS+/SyVZccudAQg/vB9P/XPec= github.com/spiffe/spire-api-sdk v1.12.0/go.mod h1:4uuhFlN6KBWjACRP3xXwrOTNnvaLp1zJs8Lribtr4fI= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= @@ -1495,8 +1497,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= -github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= gitlab.com/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8= @@ -1517,20 +1517,20 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +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/bridges/prometheus v0.60.0 h1:x7sPooQCwSg27SjtQee8GyIIRTQcF4s7eSkac6F2+VA= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0/go.mod h1:4K5UXgiHxV484efGs42ejD7E2J/sIlepYgdGoPXe7hE= -go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= -go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 h1:GuQXpvSXNjpswpweIem84U9BNauqHHi2w1GtNAalvpM= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0/go.mod h1:CkmxekdHco4d7thFJNPQ7Mby4jMBgZUclnrxT4e+ryk= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= @@ -1555,19 +1555,19 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgT go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDTe3Y= go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -1617,8 +1617,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1645,8 +1645,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1685,8 +1685,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= @@ -1769,8 +1769,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -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/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1781,8 +1781,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1794,8 +1794,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1829,8 +1829,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -1843,8 +1843,8 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.223.0 h1:JUTaWEriXmEy5AhvdMgksGGPEFsYfUKaPEYXd4c3Wvc= google.golang.org/api v0.223.0/go.mod h1:C+RS7Z+dDwds2b+zoAk5hN/eSfsiCn0UDrYof/M4d2M= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1855,10 +1855,10 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 h1:vmC/ws+pLzWjj/gzApyoZuSVrDtF1aod4u/+bbj8hgM= +google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= 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= @@ -1867,8 +1867,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +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 v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index f289be43dc..1bb6c10634 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:latest --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:aa201ad216d45d4e8c8f2512392cc8259c5daa4fa6348973235d715aa2c84c9c AS builder WORKDIR /build ADD . . @@ -16,8 +16,8 @@ COPY --from=builder /build/kapinger . CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS windows-builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:latest --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:aa201ad216d45d4e8c8f2512392cc8259c5daa4fa6348973235d715aa2c84c9c AS windows-builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index e321afcc13..18e8b45980 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS build +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:latest --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:aa201ad216d45d4e8c8f2512392cc8259c5daa4fa6348973235d715aa2c84c9c AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 2465dcf6bc..f4858ca977 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 2a3e392aaf..e152bf061c 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 3dbcd13fa8..538a0c60bb 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 0931a906d4a236b7b1865e523f016c26b22545d3 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Tue, 7 Apr 2026 16:05:12 +0100 Subject: [PATCH 293/448] feat(dependency-update): Updating multiple dependencies to mitigate all vulnerabilities (#2161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request primarily updates dependency versions in the `go.mod` and `site/package-lock.json` files. The most significant changes are dependency upgrades for both Go and Node.js packages, and the removal of an unused package. These updates help keep the project secure, compatible, and up-to-date with upstream changes. [package.json](vscode-file://vscode-app/c:/Users/itiagrawal/AppData/Local/Programs/Microsoft%20VS%20Code/cfbea10c5f/resources/app/out/vs/code/electron-browser/workbench/workbench.html) change Added an overrides section: Why: serialize-javascript@6.0.2 had two CVEs (RCE via RegExp.flags/Date.prototype.toISOString, and CPU exhaustion DoS). It's a transitive dependency pulled in by 3 webpack plugins (copy-webpack-plugin, css-minimizer-webpack-plugin, terser-webpack-plugin) via @docusaurus/bundler. Those plugins pin "^6.0.0" in their [package.json](vscode-file://vscode-app/c:/Users/itiagrawal/AppData/Local/Programs/Microsoft%20VS%20Code/cfbea10c5f/resources/app/out/vs/code/electron-browser/workbench/workbench.html), so npm won't resolve v7 automatically. The overrides field forces npm to install >=7.0.5 regardless of what the intermediate packages request. package-lock.json changes The lockfile was regenerated by npm install to reflect the override. Key diff: serialize-javascript: 6.0.2 → 7.0.5 (in 3 locations — copy-webpack-plugin, css-minimizer-webpack-plugin, terser-webpack-plugin) A few other packages got minor patch bumps as part of the normal npm install resolution refresh **Go dependency updates:** * Upgraded several indirect dependencies in `go.mod`, including `cel.dev/expr`, `github.com/cncf/xds/go`, `github.com/envoyproxy/protoc-gen-validate`, `github.com/spiffe/go-spiffe/v2`, `google.golang.org/genproto/googleapis/api`, `go.opentelemetry.io/otel`, `google.golang.org/grpc`, `github.com/go-jose/go-jose/v4`, `cloud.google.com/go/compute/metadata`, `github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp`, `github.com/buger/jsonparser`, `github.com/envoyproxy/go-control-plane/envoy`, and others. [[1]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L22-R22) [[2]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L70-R70) [[3]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L94-R94) [[4]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L190-R190) [[5]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L219-R219) [[6]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L305-R309) [[7]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L329-R328) [[8]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L341-R340) [[9]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L368-R367) [[10]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L403-R402) [[11]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L439-R438) [[12]](diffhunk://#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6L633-R639) * Removed the unused dependency `github.com/zeebo/errs` from `go.mod`. **Node.js dependency updates:** * Added `"peer": true` to many dependencies in `site/package-lock.json` to clarify peer relationships and improve package resolution. [[1]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR173) [[2]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR299) [[3]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2104) [[4]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2127) [[5]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2237) [[6]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR2659) [[7]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR3752) [[8]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR4865) [[9]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5165) [[10]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5531) [[11]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5876) [[12]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5943) [[13]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR5989) [[14]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR6599) [[15]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR7619) [[16]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR9140) [[17]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR13769) [[18]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR14345) [[19]](diffhunk://#diff-a365efb0d01e9fa4c13b70f76dd08eecbdaeecfa4e017b68471dd21c35b8866fR15219) * Removed the `randombytes` package from `site/package-lock.json`, indicating it is no longer needed.… # Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- go.mod | 2 +- go.sum | 4 ++-- site/package-lock.json | 48 ++++++++++++++++++++++++++++++------------ site/package.json | 3 +++ 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 5d90fb10f7..78fd1597cf 100644 --- a/go.mod +++ b/go.mod @@ -399,7 +399,7 @@ require ( github.com/bombsimon/wsl/v4 v4.5.0 // indirect github.com/breml/bidichk v0.3.2 // indirect github.com/breml/errchkjson v0.4.0 // indirect - github.com/buger/jsonparser v1.1.1 // indirect + github.com/buger/jsonparser v1.1.2 // indirect github.com/butuzov/ireturn v0.3.1 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/caarlos0/ctrlc v1.2.0 // indirect diff --git a/go.sum b/go.sum index dc79055af5..7c4e41305c 100644 --- a/go.sum +++ b/go.sum @@ -321,8 +321,8 @@ github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAd github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk= +github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= diff --git a/site/package-lock.json b/site/package-lock.json index 0b1afe36bc..2e2a6afa85 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -170,6 +170,7 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-common": "5.48.1", "@algolia/requester-browser-xhr": "5.48.1", @@ -295,6 +296,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2099,6 +2101,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2121,6 +2124,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2230,6 +2234,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2651,6 +2656,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3743,6 +3749,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/logger": "3.9.2", @@ -4855,6 +4862,7 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5154,6 +5162,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5519,6 +5528,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -5863,6 +5873,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5929,6 +5940,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5974,6 +5986,7 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/abtesting": "1.14.1", "@algolia/client-abtesting": "5.48.1", @@ -6583,6 +6596,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7602,6 +7616,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9122,6 +9137,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13750,6 +13766,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14325,6 +14342,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15198,6 +15216,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15973,14 +15992,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -16070,6 +16081,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16082,6 +16094,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -16134,6 +16147,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -16160,6 +16174,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17145,12 +17160,12 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=20.0.0" } }, "node_modules/serve-handler": { @@ -17311,6 +17326,7 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, + "peer": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -18251,7 +18267,8 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "peer": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18323,6 +18340,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18678,6 +18696,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18873,6 +18892,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", diff --git a/site/package.json b/site/package.json index 111dbeeb26..279aa24ccd 100644 --- a/site/package.json +++ b/site/package.json @@ -50,5 +50,8 @@ }, "engines": { "node": ">=18.0.0" + }, + "overrides": { + "serialize-javascript": ">=7.0.5" } } From 7716f76fb07ea218479cf7865de6497b56e43dff Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:44:15 +0200 Subject: [PATCH 294/448] chore(deps): bump OpenTelemetry otel/metric/trace to v1.40.0 (#2160) # Description - Bump OpenTelemetry dependencies (`otel`, `otel/metric`, `otel/trace`) to `v1.40.0`. ## Reasoning - This update includes the OpenTelemetry fix for a macOS/Darwin path hijacking issue affecting earlier versions. - Security advisory: https://github.com/microsoft/retina/security/dependabot/138 ## Risk - Low: dependency-only change (`go.mod` / `go.sum`) with no application code modifications. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 78fd1597cf..713552ed51 100644 --- a/go.mod +++ b/go.mod @@ -301,9 +301,9 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 - go.opentelemetry.io/otel v1.39.0 - go.opentelemetry.io/otel/metric v1.39.0 - go.opentelemetry.io/otel/trace v1.39.0 + go.opentelemetry.io/otel v1.40.0 + go.opentelemetry.io/otel/metric v1.40.0 + go.opentelemetry.io/otel/trace v1.40.0 go.uber.org/mock v0.5.2 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 google.golang.org/grpc v1.80.0 @@ -636,8 +636,8 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.39.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.39.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect diff --git a/go.sum b/go.sum index 7c4e41305c..965dc6f188 100644 --- a/go.sum +++ b/go.sum @@ -1529,8 +1529,8 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= -go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= @@ -1555,16 +1555,16 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgT go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDTe3Y= go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= -go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= -go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= -go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= -go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= -go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= From 39fb4dea384dc7acd5aea30a5a53e4ae528c2d56 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 9 Apr 2026 12:41:25 -0400 Subject: [PATCH 295/448] feat(dns): rewrite plugin with native cilium/ebpf (#2153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description **PR 2 of 2** for removing inspektor-gadget from retina plugins (split from #2148). Replaces the IG-based DNS tracer with a native eBPF socket filter and adds comprehensive kernel-level and Go unit tests. - **BPF program** (`dns.c`): Socket filter on AF_PACKET captures DNS queries/responses (UDP + TCP, IPv4 + IPv6). Uses `bpf_skb_load_bytes` helpers compatible with `BPF_PROG_TEST_RUN`. Query type extracted in BPF via QNAME walking. - **Per-interface dedup filter**: Socket binds to all interfaces (`ifindex=0`) with a BPF-side filter that only captures `PACKET_HOST` on non-default interfaces (veths) while capturing both directions on the default interface (eth0). This avoids double-counting while preserving visibility into same-node pod-to-CoreDNS and NodeLocal DNS traffic. - **Go plugin** (`dns_linux.go`): Perf buffer event loop with gopacket DNS parsing. Populates `dns_config` BPF map with default interface index at Init. No runtime compilation — pre-compiled via `bpf2go@v0.18.0`. - **Test infrastructure** (`ebpftest/packet.go`): `TCPPacketOpts.Payload`, IPv6 `BuildUDPPacket`, DNS packet builders (`BuildDNSQueryPacket`, `BuildDNSResponsePacket`, `BuildDNSTCPQueryPacket`). - **eBPF + unit tests**: 28 tests covering IPv4/IPv6, TCP/UDP, mDNS, edge cases, counter deltas, mock enricher, and `parseDNSPayload`. ## Related Issue Partial fix for #1788 Split from #2148 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Testing Completed All 28 tests pass (14 eBPF + 14 unit). Validated on AKS cluster (`retinaTest-v119`, 3-node, k8s v1.33.6): | Scenario | Result | |---|---| | Pod → CoreDNS same node | Captured, count=1 per query | | Pod → CoreDNS different node | Captured, count=1 per query | | NodeLocal DNS (169.254.20.10) | Both hops captured (pod→cache, cache→CoreDNS) — expected | | Multi-NIC | Not tested (single-NIC AKS nodes) | | Double-counting | None detected | Hubble and standard mode DNS metrics flowing with correct pod-level labels. ## Additional Notes - After both plugin PRs merge, inspektor-gadget can be fully removed in the Cilium v1.19 upgrade PR - The old IG tracer used `ifindex=0` with no dedup, which caused double-counting on multi-interface paths. The new BPF dedup filter resolves this while maintaining same-node and NodeLocal DNS visibility. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Quang Nguyen --- docs/03-Metrics/plugins/Linux/dns.md | 5 +- pkg/plugin/dns/_cprog/dns.c | 394 +++++++++++++++++++++++++ pkg/plugin/dns/dns_arm64_bpfel.go | 159 +++++++++++ pkg/plugin/dns/dns_arm64_bpfel.o | 0 pkg/plugin/dns/dns_ebpf_test.go | 411 +++++++++++++++++++++++++++ pkg/plugin/dns/dns_linux.go | 316 +++++++++++++++----- pkg/plugin/dns/dns_linux_test.go | 411 ++++++++++++++------------- pkg/plugin/dns/dns_x86_bpfel.go | 159 +++++++++++ pkg/plugin/dns/dns_x86_bpfel.o | 0 pkg/plugin/dns/types_linux.go | 15 +- pkg/plugin/ebpftest/packet.go | 167 +++++++++-- pkg/utils/utils_linux.go | 18 +- 12 files changed, 1763 insertions(+), 292 deletions(-) create mode 100644 pkg/plugin/dns/_cprog/dns.c create mode 100644 pkg/plugin/dns/dns_arm64_bpfel.go create mode 100644 pkg/plugin/dns/dns_arm64_bpfel.o create mode 100644 pkg/plugin/dns/dns_ebpf_test.go create mode 100644 pkg/plugin/dns/dns_x86_bpfel.go create mode 100644 pkg/plugin/dns/dns_x86_bpfel.o diff --git a/docs/03-Metrics/plugins/Linux/dns.md b/docs/03-Metrics/plugins/Linux/dns.md index eaba737e3c..1fbcdd4b1c 100644 --- a/docs/03-Metrics/plugins/Linux/dns.md +++ b/docs/03-Metrics/plugins/Linux/dns.md @@ -6,17 +6,18 @@ Tracks incoming and outgoing DNS traffic, providing various metrics and details The `dns` plugin requires the `CAP_SYS_ADMIN` capability. -- `CAP_SYS_ADMIN` is used to create a network tracer which invokes a tail call for updating the `ProgramArray` map - `NewTracer()` method at `dns_linux:50` +- `CAP_SYS_ADMIN` is used to load and attach the eBPF socket filter program ## Architecture -This plugin uses [Inspektor Gadget](https://github.com/inspektor-gadget/inspektor-gadget)'s DNS Tracer to track DNS traffic and generate basic metrics derived from the captured events. +The plugin uses a native eBPF socket filter attached to an `AF_PACKET` socket to capture DNS queries and responses. The BPF program extracts source/destination IPs, ports, and query type, then streams events to user space via a perf buffer. Go-side parsing uses `gopacket` for DNS name and response address extraction. In [Advanced mode](https://retina.sh/docs/Metrics/modes), the plugin further processes the capture results into an enriched Flow with additional Pod information. Subsequently, the Flow is transmitted to an external channel. This allows a DNS module to generate additional Pod-Level metrics. ### Code locations - Plugin and eBPF code: *pkg/plugin/dns/* +- BPF C source: *pkg/plugin/dns/_cprog/dns.c* - Module for extra Advanced metrics: *pkg/module/metrics/dns.go* ## Metrics diff --git a/pkg/plugin/dns/_cprog/dns.c b/pkg/plugin/dns/_cprog/dns.c new file mode 100644 index 0000000000..2e7c229da3 --- /dev/null +++ b/pkg/plugin/dns/_cprog/dns.c @@ -0,0 +1,394 @@ +// go:build ignore + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// DNS tracer eBPF program - captures DNS queries and responses +// +// Adapted from Inspektor Gadget's trace_dns gadget (Apache 2.0 License) +// https://github.com/inspektor-gadget/inspektor-gadget +// Copyright (c) The Inspektor Gadget authors + +#include "vmlinux.h" +#include "bpf_helpers.h" +#include "bpf_endian.h" + +char __license[] SEC("license") = "Dual MIT/GPL"; + +// Ethernet and IP constants +#define ETH_P_IP 0x0800 +#define ETH_P_IPV6 0x86DD +#define ETH_HLEN 14 + +// IP protocol constants +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 + +// IPv6 next header values +#define NEXTHDR_HOP 0 +#define NEXTHDR_TCP 6 +#define NEXTHDR_UDP 17 +#define NEXTHDR_ROUTING 43 +#define NEXTHDR_FRAGMENT 44 +#define NEXTHDR_AUTH 51 +#define NEXTHDR_NONE 59 +#define NEXTHDR_DEST 60 + +// Packet types from linux/if_packet.h +#define PACKET_HOST 0 // Incoming packets +#define PACKET_OUTGOING 4 // Outgoing packets + +// DNS constants +#define DNS_PORT 53 +#define DNS_MDNS_PORT 5353 +#define DNS_QR_QUERY 0 +#define DNS_QR_RESP 1 + +// ── Packet read helpers ── +// +// All packet reads use bpf_skb_load_bytes, which copies raw bytes from +// the sk_buff into a local variable. Unlike the legacy BPF_LD_ABS +// intrinsics (load_byte/load_half), this works with BPF_PROG_TEST_RUN +// and is the recommended approach for modern BPF programs. +// +// bpf_skb_load_bytes does NOT convert byte order — multi-byte values +// are in network byte order (big-endian) and must be converted with +// bpf_ntohs/bpf_ntohl when used as host integers. + +// Read a 1-byte value from the packet at the given offset. +static __always_inline int skb_load_byte(const struct __sk_buff *skb, + __u32 off, __u8 *out) { + return bpf_skb_load_bytes(skb, off, out, 1); +} + +// Read a 2-byte value from the packet at the given offset. +// Returns the value in host byte order. +static __always_inline int skb_load_half(const struct __sk_buff *skb, + __u32 off, __u16 *out) { + __u16 val; + int ret = bpf_skb_load_bytes(skb, off, &val, 2); + if (ret == 0) + *out = bpf_ntohs(val); + return ret; +} + +// DNS header structure (RFC 1035 §4.1.1). +// Used for sizeof and offsetof only — flag fields (QR, RCODE) are +// extracted manually to avoid bitfield portability issues. +struct dnshdr { + __u16 id; + __u16 flags; + __u16 qdcount; // Question count + __u16 ancount; // Answer count + __u16 nscount; // Authority records + __u16 arcount; // Additional records +}; + +// DNS event structure - sent to userspace. +// Fields are ordered by descending alignment (8 → 4 → 2 → 1) to avoid +// internal padding. The compiler adds 5 bytes of trailing padding to +// reach 8-byte struct alignment (required by the __u64 field). +struct dns_event { + __u64 timestamp; // Boot time in nanoseconds + __u32 src_ip; // Source IPv4 address + __u32 dst_ip; // Destination IPv4 address + __u8 src_ip6[16]; // Source IPv6 address + __u8 dst_ip6[16]; // Destination IPv6 address + __u16 src_port; // Source port + __u16 dst_port; // Destination port + __u16 id; // DNS query ID + __u16 qtype; // Query type (from first question) + __u16 ancount; // Answer count + __u16 dns_off; // DNS offset in packet + __u16 data_len; // Total packet length + __u8 af; // Address family (4 or 6) + __u8 proto; // Protocol (TCP=6, UDP=17) + __u8 pkt_type; // Packet type (HOST=0, OUTGOING=4) + __u8 qr; // Query(0) or Response(1) + __u8 rcode; // Response code +}; + +// Force bpf2go to generate a Go type for dns_event. Without this, +// bpf2go only generates types that appear in map definitions or +// program parameters. The -type flag references this symbol. +const struct dns_event *unused_dns_event __attribute__((unused)); + +// Perf event array for streaming events to userspace +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u32)); +} retina_dns_events SEC(".maps"); + +// BPF programs are limited to 512 bytes of stack (MAX_BPF_STACK in +// include/linux/filter.h: https://github.com/torvalds/linux/blob/master/include/linux/filter.h#L99), +// which is too small to hold a dns_event struct plus local variables. +// Instead we use a per-CPU array map with a single entry as heap-like +// scratch space — each CPU gets its own copy so there are no data races. +// Ref: +// https://github.com/inspektor-gadget/inspektor-gadget/blob/c414fc1/gadgets/trace_dns/program.bpf.c#L103-L109 +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, struct dns_event); +} tmp_dns_events SEC(".maps"); + +// Check if port is standard DNS (53) or mDNS (5353). +static __always_inline bool is_dns_port(__u16 port) { + return port == DNS_PORT || port == DNS_MDNS_PORT; +} + +// Socket filter attached to a raw AF_PACKET socket (bound to all interfaces). +// Filters for DNS traffic (port 53/5353), extracts header metadata into a +// dns_event struct, and sends it to userspace via perf buffer with the raw +// packet appended for Go-side DNS payload parsing. +SEC("socket1") +int retina_dns_filter(struct __sk_buff *skb) { + struct dns_event *event; + __u16 h_proto, sport, dport, l4_off, dns_off; + __u8 proto; + int zero = 0; + + // Dedupe: drop TX-side observations. Every packet has at most one + // RX-side observation in the host netns, so filtering out PACKET_OUTGOING + // gives exactly-once counting across multi-interface hosts (pod veths, + // bonded VFs, etc.). pkt_type reference: + // https://github.com/torvalds/linux/blob/master/include/linux/etherdevice.h#L615 + if (skb->pkt_type == PACKET_OUTGOING) + return 0; + + // First pass: Quick filter to check if this is a DNS packet + if (skb_load_half(skb, offsetof(struct ethhdr, h_proto), &h_proto)) + return 0; + + switch (h_proto) { + case ETH_P_IP: { + // Get IP protocol + if (skb_load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol), + &proto)) + return 0; + + // Calculate L4 offset - account for variable IP header length + __u8 ihl_byte; + if (skb_load_byte(skb, ETH_HLEN, &ihl_byte)) + return 0; + __u8 ip_header_len = (ihl_byte & 0x0F) * 4; + l4_off = ETH_HLEN + ip_header_len; + break; + } + case ETH_P_IPV6: { + // Get next header (protocol) + if (skb_load_byte(skb, ETH_HLEN + offsetof(struct ipv6hdr, nexthdr), + &proto)) + return 0; + l4_off = ETH_HLEN + sizeof(struct ipv6hdr); + +// Parse IPv6 extension headers (up to 6) +#pragma unroll + for (int i = 0; i < 6; i++) { + __u8 nextproto, ext_len; + + // Stop if we found TCP or UDP + if (proto == NEXTHDR_TCP || proto == NEXTHDR_UDP) + break; + + if (skb_load_byte(skb, l4_off, &nextproto)) + return 0; + + switch (proto) { + case NEXTHDR_FRAGMENT: + l4_off += 8; + break; + case NEXTHDR_AUTH: + if (skb_load_byte(skb, l4_off + 1, &ext_len)) + return 0; + l4_off += 4 * (ext_len + 2); + break; + case NEXTHDR_HOP: + case NEXTHDR_ROUTING: + case NEXTHDR_DEST: + if (skb_load_byte(skb, l4_off + 1, &ext_len)) + return 0; + l4_off += 8 * (ext_len + 1); + break; + case NEXTHDR_NONE: + return 0; + default: + return 0; + } + proto = nextproto; + } + break; + } + default: + return 0; + } + + // Check protocol is TCP or UDP + if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) + return 0; + + // Extract ports (same offsets for UDP and TCP) + if (skb_load_half(skb, l4_off + offsetof(struct udphdr, source), &sport)) + return 0; + if (skb_load_half(skb, l4_off + offsetof(struct udphdr, dest), &dport)) + return 0; + + // Early exit if not DNS port + if (!is_dns_port(sport) && !is_dns_port(dport)) + return 0; + + // Calculate DNS offset + switch (proto) { + case IPPROTO_UDP: + dns_off = l4_off + sizeof(struct udphdr); + break; + case IPPROTO_TCP: { + // Get TCP header length (data offset field) + __u8 doff_byte; + if (skb_load_byte(skb, l4_off + 12, &doff_byte)) + return 0; + __u8 tcp_header_len = ((doff_byte >> 4) & 0x0F) * 4; + + // Skip if no data (control segment) + dns_off = l4_off + tcp_header_len; + if (skb->len <= dns_off) + return 0; + + // DNS over TCP has 2-byte length prefix + dns_off += 2; + break; + } + default: + return 0; + } + + // Look up index 0 of the per-CPU array to get a pointer to this CPU's + // scratch buffer. The map only has one entry (max_entries=1), so index 0 + // is the only valid key. This returns a pointer the verifier trusts for + // bounded writes, unlike a raw stack allocation. + event = bpf_map_lookup_elem(&tmp_dns_events, &zero); + if (!event) + return 0; + + // Initialize event with zeros for fields that might be skipped + __builtin_memset(event, 0, sizeof(*event)); + + // Fill in event data + event->timestamp = bpf_ktime_get_boot_ns(); + event->data_len = skb->len; + event->dns_off = dns_off; + event->pkt_type = skb->pkt_type; + event->proto = proto; + event->src_port = sport; + event->dst_port = dport; + + // Extract IP addresses using bpf_skb_load_bytes for raw byte copy — + // no byte-order conversion, so the Go side gets network-order bytes + // that map directly to net.IP. + switch (h_proto) { + case ETH_P_IP: + event->af = 4; + bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, saddr), + &event->src_ip, 4); + bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr), + &event->dst_ip, 4); + break; + case ETH_P_IPV6: + event->af = 6; + bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct ipv6hdr, saddr), + event->src_ip6, 16); + bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct ipv6hdr, daddr), + event->dst_ip6, 16); + break; + } + + // Bounds check: ensure DNS header (12 bytes) fits in packet + if (skb->len < dns_off + sizeof(struct dnshdr)) + return 0; + + // Extract fields from the 12-byte DNS header (RFC 1035 §4.1.1): + // + // Offset Field + // 0-1 ID (transaction identifier) + // 2 flags[0] QR(1) | Opcode(4) | AA(1) | TC(1) | RD(1) + // 3 flags[1] RA(1) | Z(3) | RCODE(4) + // 4-5 QDCOUNT + // 6-7 ANCOUNT + // 8-9 NSCOUNT + // 10-11 ARCOUNT + // + // We read the flag bytes individually rather than using a C bitfield + // struct because bitfield layout is compiler-dependent (bit ordering + // varies between GCC and Clang, and between big/little-endian targets). + // Manual shifts give us portable, predictable extraction. + __u8 flags0, flags1; + if (skb_load_byte(skb, dns_off + 2, &flags0)) + goto send; + if (skb_load_byte(skb, dns_off + 3, &flags1)) + goto send; + event->qr = (flags0 >> 7) & 1; // QR is the high bit of flags[0] + event->rcode = flags1 & 0x0F; // RCODE is the low 4 bits of flags[1] + skb_load_half(skb, dns_off + offsetof(struct dnshdr, id), &event->id); + skb_load_half(skb, dns_off + offsetof(struct dnshdr, ancount), + &event->ancount); + + // ── Extract QTYPE (query type) from the first DNS question ── + // + // DNS question format (RFC 1035 §4.1.2): + // + // [12-byte header] ← already parsed above + // [QNAME] ← variable-length, encoded as labels + // [QTYPE] ← 2 bytes (e.g. 1=A, 28=AAAA) + // [QCLASS] ← 2 bytes (usually 1=IN) + // + // QNAME is a sequence of length-prefixed labels ending with a zero byte: + // "kubernetes.default.svc." → [10]kubernetes [7]default [3]svc [0] + // + // We read each label's length byte, skip that many bytes, and repeat + // until we hit the zero terminator. QTYPE sits right after it. + // + // The loop is bounded to 64 iterations for the BPF verifier (DNS names + // can be at most 253 bytes / ~127 labels). If the packet is truncated + // mid-name, we skip QTYPE and let the Go side extract it via gopacket. + { + __u16 qoff = dns_off + sizeof(struct dnshdr); +#pragma unroll + for (int i = 0; i < 64; i++) { + if (qoff >= skb->len) + goto send; + __u8 label_len; + if (skb_load_byte(skb, qoff, &label_len)) + goto send; + if (label_len == 0) { + qoff += 1; // skip zero terminator + break; + } + qoff += 1 + label_len; // skip length byte + label + } + if (qoff + 2 <= skb->len) + skb_load_half(skb, qoff, &event->qtype); + } + +send: + // Send the structured event + raw packet bytes to userspace in one call. + // + // bpf_perf_event_output writes `event` (sizeof(*event) bytes) into the + // perf ring buffer, then optionally appends raw packet data from `skb`. + // + // The flags parameter encodes two things: + // - Lower 32 bits: BPF_F_CURRENT_CPU — target this CPU's ring buffer + // - Upper 32 bits: skb->len — number of packet bytes to append + // + // The Go side receives a single record.RawSample containing both: + // [ dns_event struct ][ raw packet (skb->len bytes) ] + // + // It splits at sizeof(dns_event) to get the structured metadata and the + // raw DNS payload, which gopacket parses for the query name and answers. + bpf_perf_event_output(skb, &retina_dns_events, + (__u64)skb->len << 32 | BPF_F_CURRENT_CPU, event, + sizeof(*event)); + + return 0; +} diff --git a/pkg/plugin/dns/dns_arm64_bpfel.go b/pkg/plugin/dns/dns_arm64_bpfel.go new file mode 100644 index 0000000000..755a50b2c2 --- /dev/null +++ b/pkg/plugin/dns/dns_arm64_bpfel.go @@ -0,0 +1,159 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 + +package dns + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type dnsDnsEvent struct { + Timestamp uint64 + SrcIp uint32 + DstIp uint32 + SrcIp6 [16]uint8 + DstIp6 [16]uint8 + SrcPort uint16 + DstPort uint16 + Id uint16 + Qtype uint16 + Ancount uint16 + DnsOff uint16 + DataLen uint16 + Af uint8 + Proto uint8 + PktType uint8 + Qr uint8 + Rcode uint8 + _ [5]byte +} + +// loadDns returns the embedded CollectionSpec for dns. +func loadDns() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_DnsBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load dns: %w", err) + } + + return spec, err +} + +// loadDnsObjects loads dns and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *dnsObjects +// *dnsPrograms +// *dnsMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadDnsObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadDns() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// dnsSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsSpecs struct { + dnsProgramSpecs + dnsMapSpecs + dnsVariableSpecs +} + +// dnsProgramSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsProgramSpecs struct { + RetinaDnsFilter *ebpf.ProgramSpec `ebpf:"retina_dns_filter"` +} + +// dnsMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsMapSpecs struct { + RetinaDnsEvents *ebpf.MapSpec `ebpf:"retina_dns_events"` + TmpDnsEvents *ebpf.MapSpec `ebpf:"tmp_dns_events"` +} + +// dnsVariableSpecs contains global variables before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsVariableSpecs struct { + UnusedDnsEvent *ebpf.VariableSpec `ebpf:"unused_dns_event"` +} + +// dnsObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsObjects struct { + dnsPrograms + dnsMaps + dnsVariables +} + +func (o *dnsObjects) Close() error { + return _DnsClose( + &o.dnsPrograms, + &o.dnsMaps, + ) +} + +// dnsMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsMaps struct { + RetinaDnsEvents *ebpf.Map `ebpf:"retina_dns_events"` + TmpDnsEvents *ebpf.Map `ebpf:"tmp_dns_events"` +} + +func (m *dnsMaps) Close() error { + return _DnsClose( + m.RetinaDnsEvents, + m.TmpDnsEvents, + ) +} + +// dnsVariables contains all global variables after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsVariables struct { + UnusedDnsEvent *ebpf.Variable `ebpf:"unused_dns_event"` +} + +// dnsPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsPrograms struct { + RetinaDnsFilter *ebpf.Program `ebpf:"retina_dns_filter"` +} + +func (p *dnsPrograms) Close() error { + return _DnsClose( + p.RetinaDnsFilter, + ) +} + +func _DnsClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed dns_arm64_bpfel.o +var _DnsBytes []byte diff --git a/pkg/plugin/dns/dns_arm64_bpfel.o b/pkg/plugin/dns/dns_arm64_bpfel.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pkg/plugin/dns/dns_ebpf_test.go b/pkg/plugin/dns/dns_ebpf_test.go new file mode 100644 index 0000000000..6189bdc428 --- /dev/null +++ b/pkg/plugin/dns/dns_ebpf_test.go @@ -0,0 +1,411 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build ebpf && linux + +// Tests for the DNS BPF socket filter program. +// +// These load the compiled BPF program and run it against crafted packets +// using BPF_PROG_TEST_RUN, then read the per-CPU scratch map to verify +// the kernel-side parsing logic. +// +// Requires: root (or CAP_BPF+CAP_NET_ADMIN), Linux kernel 5.10+. +// Run: sudo go test -tags=ebpf -v -count=1 ./pkg/plugin/dns/... + +package dns + +import ( + "net" + "testing" + + "github.com/gopacket/gopacket/layers" + "github.com/microsoft/retina/pkg/plugin/ebpftest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// loadTestObjects loads the DNS BPF program and maps for testing. +func loadTestObjects(t *testing.T) *dnsObjects { + t.Helper() + ebpftest.RequirePrivileged(t) + + spec, err := loadDns() + require.NoError(t, err) + ebpftest.RemoveMapPinning(spec) + + var objs dnsObjects + err = spec.LoadAndAssign(&objs, nil) + require.NoError(t, err) + t.Cleanup(func() { objs.Close() }) + return &objs +} + +// --- Tests --- + +// TestDNSQueryFields sends a standard A record query and verifies all event +// fields: address family, protocol, ports, DNS ID, QR, QTYPE, IPs, and dns_off. +func TestDNSQueryFields(t *testing.T) { + objs := loadTestObjects(t) + + srcIP := net.ParseIP("10.0.0.1") + dstIP := net.ParseIP("10.0.0.2") + pkt := ebpftest.BuildDNSQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: srcIP, DstIP: dstIP, + SrcPort: 12345, DstPort: 53, + ID: 0x1234, Name: "kubernetes.default.svc", QType: layers.DNSTypeA, + }) + + ret := ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + assert.Equal(t, uint32(0), ret) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok, "expected DNS event") + + assert.Equal(t, uint8(4), event.Af, "address family") + assert.Equal(t, uint8(17), event.Proto, "protocol = UDP") + assert.Equal(t, uint16(12345), event.SrcPort) + assert.Equal(t, uint16(53), event.DstPort) + assert.Equal(t, uint16(0x1234), event.Id, "DNS ID") + assert.Equal(t, uint8(0), event.Qr, "should be query (QR=0)") + assert.Equal(t, uint16(1), event.Qtype, "QTYPE = A") + assert.Equal(t, uint16(0), event.Ancount, "query has no answers") + assert.NotZero(t, event.Timestamp) + assert.Equal(t, ebpftest.IPToNative("10.0.0.1"), event.SrcIp) + assert.Equal(t, ebpftest.IPToNative("10.0.0.2"), event.DstIp) + // dns_off = ETH(14) + IP(20) + UDP(8) = 42 + assert.Equal(t, uint16(42), event.DnsOff) +} + +// TestDNSResponseFields sends a NOERROR response with one A record answer and +// verifies QR=1, RCODE, answer count, and QTYPE extraction. +func TestDNSResponseFields(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildDNSResponsePacket(ebpftest.DNSResponseOpts{ + SrcIP: net.ParseIP("8.8.8.8"), DstIP: net.ParseIP("10.0.0.1"), + SrcPort: 53, DstPort: 40000, + ID: 0xABCD, Name: "example.com", QType: layers.DNSTypeA, + RCode: layers.DNSResponseCodeNoErr, + Answers: []net.IP{net.ParseIP("93.184.216.34")}, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok) + + assert.Equal(t, uint8(1), event.Qr, "should be response (QR=1)") + assert.Equal(t, uint8(0), event.Rcode, "RCODE = NOERROR") + assert.Equal(t, uint16(0xABCD), event.Id) + assert.Equal(t, uint16(1), event.Ancount) + assert.Equal(t, uint16(1), event.Qtype, "QTYPE = A") +} + +// TestDNSResponseNXDOMAIN verifies RCODE=3 (NXDOMAIN) is correctly extracted +// from a negative response with zero answers. +func TestDNSResponseNXDOMAIN(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildDNSResponsePacket(ebpftest.DNSResponseOpts{ + SrcIP: net.ParseIP("8.8.8.8"), DstIP: net.ParseIP("10.0.0.1"), + SrcPort: 53, DstPort: 40000, + ID: 0x5678, Name: "nxdomain.test", QType: layers.DNSTypeA, + RCode: layers.DNSResponseCodeNXDomain, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok) + + assert.Equal(t, uint8(1), event.Qr) + assert.Equal(t, uint8(3), event.Rcode, "RCODE = NXDOMAIN") + assert.Equal(t, uint16(0), event.Ancount) +} + +// TestAAAAQuery verifies QTYPE extraction for AAAA (28) queries. +func TestAAAAQuery(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildDNSQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: net.ParseIP("10.0.0.5"), DstIP: net.ParseIP("10.0.0.10"), + SrcPort: 55555, DstPort: 53, + ID: 0x9999, Name: "google.com", QType: layers.DNSTypeAAAA, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok) + + assert.Equal(t, uint16(28), event.Qtype, "QTYPE = AAAA") + assert.Equal(t, uint8(0), event.Qr) +} + +// TestIPv6DNSQuery verifies parsing of a DNS query over IPv6, including +// address family, IPv6 address extraction, and QTYPE. +func TestIPv6DNSQuery(t *testing.T) { + objs := loadTestObjects(t) + + srcIP := net.ParseIP("fd00::1") + dstIP := net.ParseIP("fd00::2") + pkt := ebpftest.BuildDNSQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: srcIP, DstIP: dstIP, + SrcPort: 44444, DstPort: 53, + ID: 0xBEEF, Name: "v6.example.com", QType: layers.DNSTypeAAAA, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok, "expected DNS event for IPv6") + + assert.Equal(t, uint8(6), event.Af, "address family = IPv6") + assert.Equal(t, uint8(17), event.Proto, "protocol = UDP") + assert.Equal(t, uint16(44444), event.SrcPort) + assert.Equal(t, uint16(53), event.DstPort) + assert.Equal(t, uint16(0xBEEF), event.Id) + assert.Equal(t, uint8(0), event.Qr, "should be query") + assert.Equal(t, uint16(28), event.Qtype, "QTYPE = AAAA") + // Verify IPv6 addresses (stored as raw 16-byte network order). + assert.Equal(t, srcIP.To16(), net.IP(event.SrcIp6[:])) + assert.Equal(t, dstIP.To16(), net.IP(event.DstIp6[:])) + // IPv4 fields should be zero for IPv6 packets. + assert.Equal(t, uint32(0), event.SrcIp) + assert.Equal(t, uint32(0), event.DstIp) + // dns_off = ETH(14) + IPv6(40) + UDP(8) = 62 + assert.Equal(t, uint16(62), event.DnsOff) +} + +// TestIPv6DNSResponse verifies parsing of a DNS response over IPv6. +func TestIPv6DNSResponse(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildDNSResponsePacket(ebpftest.DNSResponseOpts{ + SrcIP: net.ParseIP("2001:4860:4860::8888"), DstIP: net.ParseIP("fd00::1"), + SrcPort: 53, DstPort: 50000, + ID: 0xCAFE, Name: "ipv6.example.com", QType: layers.DNSTypeA, + RCode: layers.DNSResponseCodeNoErr, + Answers: []net.IP{net.ParseIP("93.184.216.34")}, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok) + + assert.Equal(t, uint8(6), event.Af, "address family = IPv6") + assert.Equal(t, uint8(1), event.Qr, "should be response") + assert.Equal(t, uint8(0), event.Rcode, "RCODE = NOERROR") + assert.Equal(t, uint16(0xCAFE), event.Id) + assert.Equal(t, uint16(1), event.Ancount) + assert.Equal(t, uint16(1), event.Qtype, "QTYPE = A") +} + +// TestMDNSPort verifies that mDNS traffic on port 5353 is recognized as DNS. +func TestMDNSPort(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildDNSQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("224.0.0.251"), + SrcPort: 5353, DstPort: 5353, + ID: 0x1111, Name: "_http._tcp.local", QType: layers.DNSTypePTR, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok) + + assert.Equal(t, uint16(5353), event.SrcPort) + assert.Equal(t, uint16(5353), event.DstPort) + assert.Equal(t, uint16(12), event.Qtype, "QTYPE = PTR") +} + +// TestMultiLabelDomain sends a query with a 15-label domain name to exercise +// the BPF QNAME walking loop and verify QTYPE is correctly extracted. +func TestMultiLabelDomain(t *testing.T) { + objs := loadTestObjects(t) + + name := "a.b.c.d.e.f.g.h.i.j.kubernetes.default.svc.cluster.local" + pkt := ebpftest.BuildDNSQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 53, + ID: 0x4242, Name: name, QType: layers.DNSTypeSRV, + }) + + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok) + + assert.Equal(t, uint16(33), event.Qtype, "QTYPE = SRV") +} + +// TestTCPDNS verifies DNS-over-TCP parsing: the BPF program must skip the TCP +// header (using the data offset field) and the 2-byte DNS length prefix. +func TestTCPDNS(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildDNSTCPQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 53, + ID: 0x7777, Name: "tcp.example.com", QType: layers.DNSTypeA, + }) + + ret := ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + assert.Equal(t, uint32(0), ret) + + event, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + require.True(t, ok, "expected DNS event for TCP") + + assert.Equal(t, uint8(6), event.Proto, "protocol = TCP") + assert.Equal(t, uint16(12345), event.SrcPort) + assert.Equal(t, uint16(53), event.DstPort) + assert.Equal(t, uint16(0x7777), event.Id) + assert.Equal(t, uint16(1), event.Qtype, "QTYPE = A") + // dns_off = ETH(14) + IP(20) + TCP(20) + len_prefix(2) = 56 + assert.Equal(t, uint16(56), event.DnsOff) +} + +// TestTCPDNSEdgeCases verifies the BPF program handles TCP edge cases without +// crashing: a SYN to port 53 with no payload, and a segment with only the +// 2-byte length prefix but no DNS data. In both cases the program may write +// a partial event to the scratch map but does NOT call bpf_perf_event_output, +// so userspace never sees it. +func TestTCPDNSEdgeCases(t *testing.T) { + t.Run("SYN no payload", func(t *testing.T) { + objs := loadTestObjects(t) + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 53, + SYN: true, + }) + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + }) + + t.Run("length prefix only", func(t *testing.T) { + objs := loadTestObjects(t) + pkt := ebpftest.BuildTCPPacket(ebpftest.TCPPacketOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 53, + PSH: true, ACK: true, + Payload: []byte{0x00, 0x20}, // claims 32 bytes but has none + }) + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + }) +} + +// TestNonDNSPort_NoEvent verifies that UDP packets to non-DNS ports (neither +// 53 nor 5353) are silently dropped without writing an event. +func TestNonDNSPort_NoEvent(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildUDPPacket(ebpftest.UDPPacketOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 8080, + PayloadSize: 20, + }) + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + _, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + assert.False(t, ok, "non-DNS port should not produce an event") +} + +// TestICMP_NoEvent verifies that non-TCP/UDP protocols are filtered out. +func TestICMP_NoEvent(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildICMPPacket(net.ParseIP("10.0.0.1"), net.ParseIP("10.0.0.2")) + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + _, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + assert.False(t, ok, "ICMP should not produce a DNS event") +} + +// TestNonIPv4_NoEvent verifies that non-IP EtherTypes (ARP) are filtered out. +func TestNonIPv4_NoEvent(t *testing.T) { + objs := loadTestObjects(t) + + pkt := ebpftest.BuildNonIPPacket(layers.EthernetTypeARP) + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + _, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + assert.False(t, ok, "ARP should not produce a DNS event") +} + +// TestMalformedPackets verifies the BPF program handles edge cases without +// crashing: runt frames, truncated IP headers, and payloads too short for +// a DNS header. +func TestMalformedPackets(t *testing.T) { + t.Run("runt packet", func(t *testing.T) { + objs := loadTestObjects(t) + pkt := ebpftest.BuildRuntPacket() + padded := append(make([]byte, 14), pkt...) //nolint:gocritic // intentional prepend + // Runt packets may be rejected by the kernel (EINVAL). Verify no panic. + _, _, err := objs.RetinaDnsFilter.Test(padded) + _ = err + }) + + t.Run("truncated IP", func(t *testing.T) { + objs := loadTestObjects(t) + pkt := ebpftest.BuildTruncatedIPPacket() + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + + _, ok := ebpftest.ReadPerCPUMap[dnsDnsEvent](t, objs.TmpDnsEvents, 0) + assert.False(t, ok, "truncated IP should not produce an event") + }) + + t.Run("UDP too short for DNS header", func(t *testing.T) { + objs := loadTestObjects(t) + // DNS port but payload < 12 bytes (DNS header size). + // BPF program writes partial event (timestamp) to scratch map but + // does NOT call bpf_perf_event_output, so userspace never sees it. + // Just verify no crash. + pkt := ebpftest.BuildUDPPacket(ebpftest.UDPPacketOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 53, + Payload: []byte{0x00, 0x01}, + }) + ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, pkt) + }) +} + +// TestReturnValue verifies the socket filter always returns 0 regardless of +// packet type. The DNS plugin captures events via perf buffer, not the +// socket filter return value. +func TestReturnValue(t *testing.T) { + objs := loadTestObjects(t) + + tests := []struct { + name string + pkt []byte + }{ + { + "DNS query", + ebpftest.BuildDNSQueryPacket(ebpftest.DNSQueryOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 12345, DstPort: 53, + ID: 1, Name: "test.com", QType: layers.DNSTypeA, + }), + }, + { + "non-DNS UDP", + ebpftest.BuildUDPPacket(ebpftest.UDPPacketOpts{ + SrcIP: net.ParseIP("10.0.0.1"), DstIP: net.ParseIP("10.0.0.2"), + SrcPort: 1000, DstPort: 8080, PayloadSize: 20, + }), + }, + { + "ICMP", + ebpftest.BuildICMPPacket(net.ParseIP("10.0.0.1"), net.ParseIP("10.0.0.2")), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ret := ebpftest.RunSocketFilter(t, objs.RetinaDnsFilter, tt.pkt) + assert.Equal(t, uint32(0), ret, "socket filter should always return 0") + }) + } +} diff --git a/pkg/plugin/dns/dns_linux.go b/pkg/plugin/dns/dns_linux.go index 9251e03e13..164f2b64cf 100644 --- a/pkg/plugin/dns/dns_linux.go +++ b/pkg/plugin/dns/dns_linux.go @@ -1,26 +1,44 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -// Package dns contains the Retina DNS plugin. It uses the Inspektor Gadget DNS tracer to capture DNS events. +// Package dns contains the Retina DNS plugin. It uses eBPF socket filters to capture DNS events. package dns import ( "context" "net" - "os" + "syscall" + "unsafe" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" - "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/dns/tracer" - "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/dns/types" - "github.com/inspektor-gadget/inspektor-gadget/pkg/utils/host" + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/perf" + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" + "github.com/microsoft/retina/internal/ktime" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/enricher" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/metrics" - "github.com/microsoft/retina/pkg/plugin/common" + plugincommon "github.com/microsoft/retina/pkg/plugin/common" "github.com/microsoft/retina/pkg/plugin/registry" "github.com/microsoft/retina/pkg/utils" + "github.com/pkg/errors" "go.uber.org/zap" + "golang.org/x/sys/unix" +) + +// Per-arch target needed because vmlinux.h differs between amd64/arm64. +// Cross-generate: GOARCH=arm64 go generate ./pkg/plugin/dns/... +// +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go@v0.18.0 -cflags "-Wall" -target ${GOARCH} -type dns_event dns ./_cprog/dns.c -- -I../lib/_${GOARCH} -I../lib/common/libbpf/_src + +const ( + // perCPUBuffer is the max number of pages passed to NewPerfReader. + // The reader tries this first, then halves until allocation succeeds. + perCPUBuffer = 8192 + recordsBuffer = 1000 // Channel buffer for records + workers = 2 // Number of worker goroutines ) func init() { @@ -38,30 +56,58 @@ func (d *dns) Name() string { return name } -func (d *dns) Generate(ctx context.Context) error { - return nil -} - -func (d *dns) Compile(ctx context.Context) error { - return nil -} +// Generate and Compile are no-ops. The plugin manager lifecycle requires them, +// but DNS uses bpf2go which pre-compiles the BPF program at build time and +// embeds it in the binary — no runtime code generation or compilation needed. +func (d *dns) Generate(_ context.Context) error { return nil } +func (d *dns) Compile(_ context.Context) error { return nil } func (d *dns) Init() error { - // Create tracer. In this case no parameters are passed. - err := host.Init(host.Config{}) - tracer, err := tracer.NewTracer() + objs := &dnsObjects{} + if err := loadDnsObjects(objs, &ebpf.CollectionOptions{ + Maps: ebpf.MapOptions{ + PinPath: plugincommon.MapPath, + }, + }); err != nil { + return errors.Wrap(err, "failed to load eBPF objects") + } + + // Bind to all interfaces (ifindex=0). The BPF program dedupes by + // capturing only PACKET_HOST — see dns.c for the filter logic. + sock, err := utils.OpenRawSocket(0) if err != nil { - d.l.Error("Failed to create tracer", zap.Error(err)) - return err + objs.Close() + return errors.Wrap(err, "failed to open raw socket") } - d.tracer = tracer - d.tracer.SetEventHandler(d.eventHandler) - d.pid = uint32(os.Getpid()) - d.l.Info("Initialized dns plugin") + + fd := objs.RetinaDnsFilter.FD() + if err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, unix.SO_ATTACH_BPF, fd); err != nil { + syscall.Close(sock) //nolint:errcheck // best-effort cleanup + objs.Close() + return errors.Wrap(err, "failed to attach BPF to socket") + } + + reader, err := plugincommon.NewPerfReader(d.l, objs.RetinaDnsEvents, perCPUBuffer, 1) + if err != nil { + syscall.Close(sock) //nolint:errcheck // best-effort cleanup + objs.Close() + return errors.Wrap(err, "failed to create perf reader") + } + + // Only assign to struct fields after all setup succeeds, + // so partial Init failures don't leave dangling resources. + d.objs = objs + d.sock = sock + d.reader = reader + + d.l.Info("DNS plugin initialized") return nil } func (d *dns) Start(ctx context.Context) error { + d.isRunning = true + d.recordsChannel = make(chan perf.Record, recordsBuffer) + if d.cfg.EnablePodLevel { if enricher.IsInitialized() { d.enricher = enricher.Instance() @@ -69,89 +115,165 @@ func (d *dns) Start(ctx context.Context) error { d.l.Warn("retina enricher is not initialized") } } - if err := d.tracer.Attach(d.pid); err != nil { - d.l.Error("Failed to attach tracer", zap.Error(err)) - return err + + return d.run(ctx) +} + +func (d *dns) run(ctx context.Context) error { + for i := range workers { + d.wg.Add(1) + go d.processRecord(ctx, i) } + // readEvents is not tracked by wg — it blocks inside reader.Read() which + // is only unblocked by reader.Close() in Stop(). The lifecycle is: + // ctx cancel → run() returns → Stop() → reader.Close() → readEvents exits. + go d.readEvents(ctx) <-ctx.Done() + d.wg.Wait() return nil } -func (d *dns) Stop() error { - if d.tracer != nil { - d.tracer.Detach(d.pid) - d.tracer.Close() +func (d *dns) readEvents(ctx context.Context) { + for { + // Note: ctx.Done is only checked between Read() calls. Once blocked + // inside Read(), only reader.Close() (called from Stop) unblocks it. + select { + case <-ctx.Done(): + return + default: + record, err := d.reader.Read() + if err != nil { + if errors.Is(err, perf.ErrClosed) { + return + } + d.l.Error("Error reading perf event", zap.Error(err)) + continue + } + + if record.LostSamples > 0 { + metrics.LostEventsCounter.WithLabelValues(utils.Kernel, name).Add(float64(record.LostSamples)) + continue + } + + select { + case d.recordsChannel <- record: + default: + metrics.LostEventsCounter.WithLabelValues(utils.BufferedChannel, name).Inc() + } + } } - d.l.Info("Stopped dns plugin") - return nil } -func (d *dns) SetupChannel(c chan *v1.Event) error { - d.externalChannel = c - return nil +func (d *dns) processRecord(ctx context.Context, _ int) { + defer d.wg.Done() + + for { + select { + case <-ctx.Done(): + return + case record := <-d.recordsChannel: + d.handleDNSEvent(record) + } + } } -func (d *dns) eventHandler(event *types.Event) { - if event == nil { +func (d *dns) handleDNSEvent(record perf.Record) { + eventSize := int(unsafe.Sizeof(dnsDnsEvent{})) + if len(record.RawSample) < eventSize { return } - d.l.Debug("Event received", zap.Any("event", event)) - // Update basic metrics - if event.Qr == types.DNSPktTypeQuery { - m = metrics.DNSRequestCounter - } else if event.Qr == types.DNSPktTypeResponse { - m = metrics.DNSResponseCounter + event := (*dnsDnsEvent)(unsafe.Pointer(&record.RawSample[0])) //nolint:gosec // perf record is aligned + + // Increment basic counter (always, regardless of pod-level) + if event.Qr == 0 { + metrics.DNSRequestCounter.WithLabelValues().Inc() } else { - return + metrics.DNSResponseCounter.WithLabelValues().Inc() } - m.WithLabelValues().Inc() if !d.cfg.EnablePodLevel { return } + // Unlike the old IG tracer which observed both ingress and egress per + // endpoint, this plugin only sees each packet once — the BPF filter + // drops PACKET_OUTGOING so only RX-side observations remain (see dns.c). + // We derive direction from QR: queries are egress, responses are ingress. + const ( + dirIngress uint8 = 2 + dirEgress uint8 = 3 + ) var dir uint8 - if event.PktType == "HOST" { - // Ingress. - dir = 2 - } else if event.PktType == "OUTGOING" { - // Egress. - dir = 3 + if event.Qr == 0 { + dir = dirEgress } else { + dir = dirIngress + } + + // IP addresses — copy raw bytes, no endian conversion needed + var srcIP, dstIP net.IP + switch event.Af { + case 4: + var srcBuf, dstBuf [net.IPv4len]byte + *(*uint32)(unsafe.Pointer(&srcBuf[0])) = event.SrcIp //nolint:gosec // same size + *(*uint32)(unsafe.Pointer(&dstBuf[0])) = event.DstIp //nolint:gosec // same size + srcIP = srcBuf[:] + dstIP = dstBuf[:] + case 6: + srcIP = event.SrcIp6[:] + dstIP = event.DstIp6[:] + default: return } - // Update advanced metrics. + // Parse DNS name and response addresses from the packet payload. + var dnsName string + var addresses []string + var qtype layers.DNSType + if packetData := record.RawSample[eventSize:]; len(packetData) > 0 && int(event.DnsOff) < len(packetData) { + dnsName, addresses, qtype = d.parseDNSPayload(packetData[event.DnsOff:], event.Qr == 1) + } + // Prefer BPF-extracted qtype; fall back to gopacket if BPF couldn't + // parse it (e.g. truncated name, packet too short). + if event.Qtype != 0 { + qtype = layers.DNSType(event.Qtype) + } + qTypes := []string{qtype.String()} + + var qrStr string + if event.Qr == 0 { + qrStr = "Q" + } else { + qrStr = "R" + } + fl := utils.ToFlow( d.l, - int64(event.Timestamp), - net.ParseIP(event.SrcIP), - net.ParseIP(event.DstIP), - uint32(event.SrcPort), - uint32(event.DstPort), - uint8(common.ProtocolToFlow(event.Protocol)), - dir, + ktime.MonotonicOffset.Nanoseconds()+int64(event.Timestamp), //nolint:gosec // timestamp fits in int64 + srcIP, dstIP, + uint32(event.SrcPort), uint32(event.DstPort), + event.Proto, dir, utils.Verdict_DNS, ) + if fl == nil { + return + } ext := utils.NewExtensions() - - utils.AddDNSInfo(fl, ext, string(event.Qr), common.RCodeToFlow(event.Rcode), event.DNSName, []string{event.QType}, event.NumAnswers, event.Addresses) - - // Set extensions on the flow. + utils.AddDNSInfo(fl, ext, qrStr, uint32(event.Rcode), dnsName, qTypes, int(event.Ancount), addresses) utils.SetExtensions(fl, ext) - ev := (&v1.Event{ + ev := &v1.Event{ Event: fl, Timestamp: fl.GetTime(), - }) + } + if d.enricher != nil { d.enricher.Write(ev) } - // Send event to external channel. if d.externalChannel != nil { select { case d.externalChannel <- ev: @@ -160,3 +282,67 @@ func (d *dns) eventHandler(event *types.Event) { } } } + +// parseDNSPayload extracts the query name, response addresses, and query type +// from the raw DNS payload using gopacket. +//nolint:nonamedreturns // named returns used by defer recovery +func (d *dns) parseDNSPayload(payload []byte, isResponse bool) ( + dnsName string, addresses []string, qtype layers.DNSType, +) { + if len(payload) < 12 { + return "", nil, 0 + } + + // gopacket's DNS decoder can panic on malformed input. + defer func() { + if r := recover(); r != nil { + d.l.Debug("DNS decode panic (malformed packet)", zap.Any("recover", r)) + dnsName, addresses, qtype = "", nil, 0 + } + }() + + var parser layers.DNS + if err := parser.DecodeFromBytes(payload, gopacket.NilDecodeFeedback); err != nil { + return "", nil, 0 + } + + if len(parser.Questions) > 0 { + dnsName = string(parser.Questions[0].Name) + "." + qtype = parser.Questions[0].Type + } + + if isResponse { + for i := range parser.Answers { + if parser.Answers[i].IP != nil { + addresses = append(addresses, parser.Answers[i].IP.String()) + } + } + } + + return dnsName, addresses, qtype +} + +func (d *dns) Stop() error { + if !d.isRunning { + return nil + } + if d.reader != nil { + d.reader.Close() + } + if d.recordsChannel != nil { + close(d.recordsChannel) + } + if d.sock != 0 { + syscall.Close(d.sock) //nolint:errcheck // best-effort cleanup + } + if d.objs != nil { + d.objs.Close() + } + d.isRunning = false + return nil +} + +func (d *dns) SetupChannel(c chan *v1.Event) error { + d.externalChannel = c + return nil +} diff --git a/pkg/plugin/dns/dns_linux_test.go b/pkg/plugin/dns/dns_linux_test.go index 397c10dc55..ea10ee1e36 100644 --- a/pkg/plugin/dns/dns_linux_test.go +++ b/pkg/plugin/dns/dns_linux_test.go @@ -1,253 +1,284 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -//nolint:typecheck package dns import ( "context" - "errors" - "reflect" + "net" + "os" "testing" - "time" + "unsafe" - "github.com/cilium/cilium/api/v1/flow" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" - "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/dns/types" + "github.com/cilium/ebpf/perf" + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" "github.com/microsoft/retina/pkg/config" - "github.com/microsoft/retina/pkg/controllers/cache" "github.com/microsoft/retina/pkg/enricher" "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/metrics" - "github.com/microsoft/retina/pkg/plugin/common/mocks" - "github.com/microsoft/retina/pkg/pubsub" - "github.com/microsoft/retina/pkg/utils" - "github.com/prometheus/client_golang/prometheus" - dto "github.com/prometheus/client_model/go" + "github.com/prometheus/client_golang/prometheus/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" - "gotest.tools/v3/assert" ) -func TestStop(t *testing.T) { +func TestMain(m *testing.M) { log.SetupZapLogger(log.GetDefaultLogOpts()) - d := &dns{ - l: log.Logger().Named(name), - pid: 1234, - } - // Check nil tracer. - d.Stop() - - // Check with tracer. - ctrl := gomock.NewController(t) - defer ctrl.Finish() - m := mocks.NewMockITracer(ctrl) - m.EXPECT().Detach(d.pid).Return(nil).Times(1) - m.EXPECT().Close().Times(1) - d.tracer = m - d.Stop() + metrics.InitializeMetrics() + os.Exit(m.Run()) } -func TestStart(t *testing.T) { - ctxTimeout, cancel := context.WithTimeout(context.Background(), 3*time.Second) - defer cancel() - - log.SetupZapLogger(log.GetDefaultLogOpts()) - - c := cache.New(pubsub.New()) - e := enricher.New(ctxTimeout, c) - e.Run() - defer e.Reader.Close() +func TestNew(t *testing.T) { + cfg := &config.Config{EnablePodLevel: true} + d := New(cfg) + require.NotNil(t, d) + assert.Equal(t, name, d.Name()) +} +func TestStop(t *testing.T) { d := &dns{ + cfg: &config.Config{EnablePodLevel: true}, l: log.Logger().Named(name), - pid: 1234, - cfg: &config.Config{ - EnablePodLevel: true, - }, } + // Should not panic when not running. + require.NoError(t, d.Stop()) +} - ctrl := gomock.NewController(t) - defer ctrl.Finish() - m := mocks.NewMockITracer(ctrl) - m.EXPECT().Attach(d.pid).Return(nil).Times(1) - d.tracer = m - err := d.Start(ctxTimeout) - assert.Equal(t, err, nil) - if d.enricher == nil { - t.Fatal("enricher is nil") +func TestSetupChannel(t *testing.T) { + d := &dns{ + cfg: &config.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), } + ch := make(chan *v1.Event, 10) + require.NoError(t, d.SetupChannel(ch)) + assert.Equal(t, ch, d.externalChannel) +} - // Test error case. - expected := errors.New("Error") - m = mocks.NewMockITracer(ctrl) - m.EXPECT().Attach(d.pid).Return(expected).Times(1) - d.tracer = m +func TestGenerate(t *testing.T) { + d := &dns{cfg: &config.Config{}, l: log.Logger().Named(name)} + require.NoError(t, d.Generate(context.Background())) +} - err = d.Start(ctxTimeout) - assert.Error(t, err, expected.Error()) +// buildTestRecord creates a synthetic perf.Record containing a dns_event struct +// followed by raw packet bytes, mimicking what the BPF program produces. +// The struct is reinterpreted as raw bytes via unsafe — the same layout the +// BPF perf ring uses, so handleDNSEvent's unsafe cast works correctly. +func buildTestRecord(event dnsDnsEvent, packetData []byte) perf.Record { + eventSize := int(unsafe.Sizeof(event)) + eventBytes := unsafe.Slice((*byte)(unsafe.Pointer(&event)), eventSize) //nolint:gosec // test-only + buf := make([]byte, eventSize+len(packetData)) + copy(buf, eventBytes) + copy(buf[eventSize:], packetData) + return perf.Record{RawSample: buf} } -func TestMalformedEventHandler(t *testing.T) { - log.SetupZapLogger(log.GetDefaultLogOpts()) +// TestHandleDNSEvent_RequestCounter verifies the request counter increments +// for QR=0 events when pod-level is disabled (only counters, no flow). +func TestHandleDNSEvent_RequestCounter(t *testing.T) { d := &dns{ - l: log.Logger().Named(name), + cfg: &config.Config{EnablePodLevel: false}, + l: log.Logger().Named(name), } + before := testutil.ToFloat64(metrics.DNSRequestCounter.WithLabelValues()) + record := buildTestRecord(dnsDnsEvent{Timestamp: 1000, Qr: 0}, nil) + d.handleDNSEvent(record) + after := testutil.ToFloat64(metrics.DNSRequestCounter.WithLabelValues()) + assert.InDelta(t, before+1, after, 0, "request counter should increment by 1") +} - // Test nil event. - m = nil - d.eventHandler(nil) - assert.Equal(t, m, nil) - - // Test event with no Query type. - m = nil - event := &types.Event{ - Qr: "Z", +// TestHandleDNSEvent_ResponseCounter verifies the response counter increments +// for QR=1 events. +func TestHandleDNSEvent_ResponseCounter(t *testing.T) { + d := &dns{ + cfg: &config.Config{EnablePodLevel: false}, + l: log.Logger().Named(name), } - d.eventHandler(event) - assert.Equal(t, m, nil) + before := testutil.ToFloat64(metrics.DNSResponseCounter.WithLabelValues()) + record := buildTestRecord(dnsDnsEvent{Timestamp: 2000, Qr: 1, Rcode: 3}, nil) + d.handleDNSEvent(record) + after := testutil.ToFloat64(metrics.DNSResponseCounter.WithLabelValues()) + assert.InDelta(t, before+1, after, 0, "response counter should increment by 1") } -func TestRequestEventHandler(t *testing.T) { - log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() +// TestHandleDNSEvent_TooShortRecord verifies a record shorter than the event +// struct is silently skipped (no counter change). +func TestHandleDNSEvent_TooShortRecord(t *testing.T) { + d := &dns{ + cfg: &config.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + } + reqBefore := testutil.ToFloat64(metrics.DNSRequestCounter.WithLabelValues()) + respBefore := testutil.ToFloat64(metrics.DNSResponseCounter.WithLabelValues()) + record := perf.Record{RawSample: []byte{0x01, 0x02, 0x03}} + d.handleDNSEvent(record) + assert.InDelta(t, reqBefore, testutil.ToFloat64(metrics.DNSRequestCounter.WithLabelValues()), 0) + assert.InDelta(t, respBefore, testutil.ToFloat64(metrics.DNSResponseCounter.WithLabelValues()), 0) +} +// TestHandleDNSEvent_PktTypeIgnored verifies that pkt_type does not affect +// flow emission — direction is derived from QR, not pkt_type. Even +// PACKET_OUTGOING (normally filtered by BPF) produces a flow if it somehow +// reaches userspace. +func TestHandleDNSEvent_PktTypeIgnored(t *testing.T) { + ch := make(chan *v1.Event, 10) d := &dns{ - l: log.Logger().Named(name), - cfg: &config.Config{ - EnablePodLevel: true, - }, + cfg: &config.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + externalChannel: ch, } + record := buildTestRecord(dnsDnsEvent{ + Timestamp: 1000, Af: 4, PktType: 4, // PACKET_OUTGOING (filtered by BPF, not by Go) + SrcIp: 0x0100000A, DstIp: 0x0200000A, + }, nil) + d.handleDNSEvent(record) + assert.Len(t, ch, 1, "pkt_type should not affect flow emission; direction comes from QR") +} - // Test event with Query type. - m = nil - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - event := &types.Event{ - Qr: "Q", - Rcode: "No Error", - QType: "A", - DNSName: "test.com", - Addresses: []string{}, - NumAnswers: 0, - PktType: "OUTGOING", - SrcIP: "1.1.1.1", - DstIP: "2.2.2.2", - SrcPort: 58, - DstPort: 8080, - Protocol: "TCP", +// TestHandleDNSEvent_UnknownAF verifies packets with an unknown address family +// are dropped when pod-level is enabled. +func TestHandleDNSEvent_UnknownAF(t *testing.T) { + ch := make(chan *v1.Event, 10) + d := &dns{ + cfg: &config.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + externalChannel: ch, } - c := prometheus.NewCounter(prometheus.CounterOpts{}) + record := buildTestRecord(dnsDnsEvent{ + Timestamp: 1000, Af: 99, PktType: 0, + }, nil) + d.handleDNSEvent(record) + assert.Empty(t, ch, "unknown AF should not emit a flow") +} - // Basic metrics. - mockCV := metrics.NewMockCounterVec(ctrl) - mockCV.EXPECT().WithLabelValues().Return(c).Times(1) - before := value(c) - metrics.DNSRequestCounter = mockCV +// TestParseDNSPayload_Query verifies query name and type extraction. +func TestParseDNSPayload_Query(t *testing.T) { + d := &dns{l: log.Logger().Named(name)} - // Advanced metrics. - mockEnricher := enricher.NewMockEnricherInterface(ctrl) - mockEnricher.EXPECT().Write(EventMatched( - utils.DNSType_QUERY, 0, event.DNSName, []string{event.QType}, 0, []string{}, - )).Times(1) - d.enricher = mockEnricher + payload := buildMinimalDNSQuery("example.com", 1) + dnsName, addresses, qtype := d.parseDNSPayload(payload, false) - d.eventHandler(event) - after := value(c) - assert.Equal(t, after-before, float64(1)) + assert.Equal(t, "example.com.", dnsName) + assert.Empty(t, addresses) + assert.Equal(t, uint16(1), uint16(qtype)) } -func TestResponseEventHandler(t *testing.T) { - log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() +// TestParseDNSPayload_Response verifies response parsing with an A record. +func TestParseDNSPayload_Response(t *testing.T) { + d := &dns{l: log.Logger().Named(name)} - d := &dns{ - l: log.Logger().Named(name), - cfg: &config.Config{ - EnablePodLevel: true, - }, - } + payload := buildMinimalDNSResponse("test.local", 1, net.ParseIP("1.2.3.4")) + dnsName, addresses, qtype := d.parseDNSPayload(payload, true) - // Test event with Query type. - m = nil - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - event := &types.Event{ - Qr: "R", - Rcode: "No Error", - QType: "A", - DNSName: "test.com", - Addresses: []string{"1.1.1.1", "2.2.2.2"}, - NumAnswers: 2, - PktType: "HOST", - SrcIP: "1.1.1.1", - DstIP: "2.2.2.2", - SrcPort: 58, - DstPort: 8080, - Protocol: "TCP", - } + assert.Equal(t, "test.local.", dnsName) + assert.Equal(t, uint16(1), uint16(qtype)) + require.Len(t, addresses, 1) + assert.Equal(t, "1.2.3.4", addresses[0]) +} - // Basic metrics. - c := prometheus.NewCounter(prometheus.CounterOpts{}) - mockCV := metrics.NewMockCounterVec(ctrl) - mockCV.EXPECT().WithLabelValues().Return(c).Times(1) - before := value(c) - metrics.DNSResponseCounter = mockCV +// TestParseDNSPayload_TooShort verifies payloads under 12 bytes return empty. +func TestParseDNSPayload_TooShort(t *testing.T) { + d := &dns{l: log.Logger().Named(name)} - // Advanced metrics. - mockEnricher := enricher.NewMockEnricherInterface(ctrl) - mockEnricher.EXPECT().Write(EventMatched( - utils.DNSType_RESPONSE, 0, event.DNSName, []string{event.QType}, 2, []string{"1.1.1.1", "2.2.2.2"}, - )).Times(1) - d.enricher = mockEnricher + dnsName, addresses, qtype := d.parseDNSPayload([]byte{0x00, 0x01}, false) - d.eventHandler(event) - after := value(c) - assert.Equal(t, after-before, float64(1)) + assert.Empty(t, dnsName) + assert.Nil(t, addresses) + assert.Equal(t, uint16(0), uint16(qtype)) } -func value(c prometheus.Counter) float64 { - m := &dto.Metric{} - c.Write(m) - - return m.Counter.GetValue() +// TestParseDNSPayload_Malformed verifies malformed DNS payloads don't panic. +func TestParseDNSPayload_Malformed(t *testing.T) { + d := &dns{l: log.Logger().Named(name)} + + // 12-byte header with QDCOUNT=1 but no question data. + payload := make([]byte, 20) + payload[4] = 0x00 + payload[5] = 0x01 + assert.NotPanics(t, func() { + d.parseDNSPayload(payload, false) + }) } -// Helpers. +// TestHandleDNSEvent_WithPacketData verifies handleDNSEvent processes a +// complete event with attached packet data, writes to the enricher, and +// emits a flow to the external channel with correct DNS info. +func TestHandleDNSEvent_WithPacketData(t *testing.T) { + ctrl := gomock.NewController(t) -type EventMatcher struct { - qType utils.DNSType - rCode uint32 - query string - qTypes []string - numAnswers uint32 - ips []string -} + menricher := enricher.NewMockEnricherInterface(ctrl) //nolint:typecheck + menricher.EXPECT().Write(gomock.Any()).MinTimes(1) + + ch := make(chan *v1.Event, 10) + d := &dns{ + cfg: &config.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + enricher: menricher, + externalChannel: ch, + } -func (m *EventMatcher) Matches(x interface{}) bool { - inputFlow := x.(*v1.Event).Event.(*flow.Flow) - expectedDNS, expectedDNSType, expectedNumResponses := utils.GetDNS(inputFlow) - return expectedDNS != nil && - expectedDNS.GetRcode() == m.rCode && - expectedDNS.GetQuery() == m.query && - reflect.DeepEqual(expectedDNS.GetIps(), m.ips) && - reflect.DeepEqual(expectedDNS.GetQtypes(), m.qTypes) && - expectedDNSType == m.qType && - expectedNumResponses == m.numAnswers + dnsPayload := buildMinimalDNSQuery("k8s.io", 1) + // Build a minimal packet: Ethernet(14) + IP(20) + UDP(8) + DNS. + // dns_off = 42 points to the DNS payload within the packet. + pktData := make([]byte, 42+len(dnsPayload)) + copy(pktData[42:], dnsPayload) + + record := buildTestRecord(dnsDnsEvent{ + Timestamp: 5000, + Af: 4, + Proto: 17, + PktType: 0, // PACKET_HOST + Qr: 0, + Qtype: 1, + SrcPort: 12345, + DstPort: 53, + DnsOff: 42, + SrcIp: 0x0100000A, // 10.0.0.1 + DstIp: 0x0200000A, // 10.0.0.2 + }, pktData) + + d.handleDNSEvent(record) + + require.Len(t, ch, 1, "expected one flow on the external channel") + ev := <-ch + fl := ev.GetFlow() + require.NotNil(t, fl) + assert.NotNil(t, fl.GetL4().GetUDP()) + assert.Equal(t, uint32(53), fl.GetL4().GetUDP().GetDestinationPort()) + assert.NotNil(t, fl.GetExtensions()) } -func (m *EventMatcher) String() string { - return "is anything" +// --- DNS payload helpers --- + +func buildMinimalDNSQuery(name string, qtype uint16) []byte { + buf := gopacket.NewSerializeBuffer() + dns := &layers.DNS{ + ID: 1, RD: true, QDCount: 1, + Questions: []layers.DNSQuestion{{ + Name: []byte(name), Type: layers.DNSType(qtype), Class: layers.DNSClassIN, + }}, + } + if err := dns.SerializeTo(buf, gopacket.SerializeOptions{FixLengths: true}); err != nil { + panic("failed to serialize DNS query: " + err.Error()) + } + return buf.Bytes() } -func EventMatched(qType utils.DNSType, rCode uint32, query string, qTypes []string, numAnswers uint32, ips []string) gomock.Matcher { - return &EventMatcher{ - qType: qType, - rCode: rCode, - query: query, - qTypes: qTypes, - numAnswers: numAnswers, - ips: ips, +func buildMinimalDNSResponse(name string, qtype uint16, answerIP net.IP) []byte { + buf := gopacket.NewSerializeBuffer() + dns := &layers.DNS{ + ID: 1, QR: true, RD: true, QDCount: 1, ANCount: 1, + Questions: []layers.DNSQuestion{{ + Name: []byte(name), Type: layers.DNSType(qtype), Class: layers.DNSClassIN, + }}, + Answers: []layers.DNSResourceRecord{{ + Name: []byte(name), Type: layers.DNSType(qtype), Class: layers.DNSClassIN, + TTL: 60, IP: answerIP, + }}, + } + if err := dns.SerializeTo(buf, gopacket.SerializeOptions{FixLengths: true}); err != nil { + panic("failed to serialize DNS response: " + err.Error()) } + return buf.Bytes() } diff --git a/pkg/plugin/dns/dns_x86_bpfel.go b/pkg/plugin/dns/dns_x86_bpfel.go new file mode 100644 index 0000000000..61b3098ea8 --- /dev/null +++ b/pkg/plugin/dns/dns_x86_bpfel.go @@ -0,0 +1,159 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 + +package dns + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type dnsDnsEvent struct { + Timestamp uint64 + SrcIp uint32 + DstIp uint32 + SrcIp6 [16]uint8 + DstIp6 [16]uint8 + SrcPort uint16 + DstPort uint16 + Id uint16 + Qtype uint16 + Ancount uint16 + DnsOff uint16 + DataLen uint16 + Af uint8 + Proto uint8 + PktType uint8 + Qr uint8 + Rcode uint8 + _ [5]byte +} + +// loadDns returns the embedded CollectionSpec for dns. +func loadDns() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_DnsBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load dns: %w", err) + } + + return spec, err +} + +// loadDnsObjects loads dns and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *dnsObjects +// *dnsPrograms +// *dnsMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadDnsObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadDns() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// dnsSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsSpecs struct { + dnsProgramSpecs + dnsMapSpecs + dnsVariableSpecs +} + +// dnsProgramSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsProgramSpecs struct { + RetinaDnsFilter *ebpf.ProgramSpec `ebpf:"retina_dns_filter"` +} + +// dnsMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsMapSpecs struct { + RetinaDnsEvents *ebpf.MapSpec `ebpf:"retina_dns_events"` + TmpDnsEvents *ebpf.MapSpec `ebpf:"tmp_dns_events"` +} + +// dnsVariableSpecs contains global variables before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type dnsVariableSpecs struct { + UnusedDnsEvent *ebpf.VariableSpec `ebpf:"unused_dns_event"` +} + +// dnsObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsObjects struct { + dnsPrograms + dnsMaps + dnsVariables +} + +func (o *dnsObjects) Close() error { + return _DnsClose( + &o.dnsPrograms, + &o.dnsMaps, + ) +} + +// dnsMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsMaps struct { + RetinaDnsEvents *ebpf.Map `ebpf:"retina_dns_events"` + TmpDnsEvents *ebpf.Map `ebpf:"tmp_dns_events"` +} + +func (m *dnsMaps) Close() error { + return _DnsClose( + m.RetinaDnsEvents, + m.TmpDnsEvents, + ) +} + +// dnsVariables contains all global variables after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsVariables struct { + UnusedDnsEvent *ebpf.Variable `ebpf:"unused_dns_event"` +} + +// dnsPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadDnsObjects or ebpf.CollectionSpec.LoadAndAssign. +type dnsPrograms struct { + RetinaDnsFilter *ebpf.Program `ebpf:"retina_dns_filter"` +} + +func (p *dnsPrograms) Close() error { + return _DnsClose( + p.RetinaDnsFilter, + ) +} + +func _DnsClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed dns_x86_bpfel.o +var _DnsBytes []byte diff --git a/pkg/plugin/dns/dns_x86_bpfel.o b/pkg/plugin/dns/dns_x86_bpfel.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pkg/plugin/dns/types_linux.go b/pkg/plugin/dns/types_linux.go index 9517cc9b2f..a91475708c 100644 --- a/pkg/plugin/dns/types_linux.go +++ b/pkg/plugin/dns/types_linux.go @@ -3,23 +3,26 @@ package dns import ( + "sync" + v1 "github.com/cilium/cilium/pkg/hubble/api/v1" + "github.com/cilium/ebpf/perf" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/enricher" "github.com/microsoft/retina/pkg/log" - "github.com/microsoft/retina/pkg/metrics" - "github.com/microsoft/retina/pkg/plugin/common" ) const name = "dns" -var m metrics.CounterVec - type dns struct { cfg *kcfg.Config l *log.ZapLogger - tracer common.ITracer - pid uint32 enricher enricher.EnricherInterface externalChannel chan *v1.Event + objs *dnsObjects + reader *perf.Reader + sock int + isRunning bool + recordsChannel chan perf.Record + wg sync.WaitGroup } diff --git a/pkg/plugin/ebpftest/packet.go b/pkg/plugin/ebpftest/packet.go index 061ca2c6d8..ea1a94dda9 100644 --- a/pkg/plugin/ebpftest/packet.go +++ b/pkg/plugin/ebpftest/packet.go @@ -26,8 +26,9 @@ type TCPPacketOpts struct { RST, PSH, URG bool ECE, CWR bool SeqNum, AckNum uint32 - TSval, TSecr uint32 // Zero means omit TCP timestamp option. - PayloadSize int + TSval, TSecr uint32 // Zero means omit TCP timestamp option. + Payload []byte // Raw payload bytes. If nil, PayloadSize zero bytes are used. + PayloadSize int // Ignored when Payload is set. } // BuildTCPPacket constructs a valid Ethernet + IPv4 + TCP packet. @@ -76,7 +77,10 @@ func BuildTCPPacket(opts TCPPacketOpts) []byte { tcp.SetNetworkLayerForChecksum(ip) - payload := make([]byte, opts.PayloadSize) + payload := opts.Payload + if payload == nil { + payload = make([]byte, opts.PayloadSize) + } buf := gopacket.NewSerializeBuffer() serializeOpts := gopacket.SerializeOptions{ @@ -101,50 +105,157 @@ type UDPPacketOpts struct { PayloadSize int // Ignored when Payload is set. } -// BuildUDPPacket constructs a valid Ethernet + IPv4 + UDP packet. +// BuildUDPPacket constructs a valid Ethernet + IP + UDP packet. +// Automatically selects IPv4 or IPv6 based on the source IP address. func BuildUDPPacket(opts UDPPacketOpts) []byte { - eth := &layers.Ethernet{ - SrcMAC: DefaultSrcMAC, - DstMAC: DefaultDstMAC, - EthernetType: layers.EthernetTypeIPv4, - } - - ip := &layers.IPv4{ - Version: 4, - IHL: 5, - TTL: 64, - Protocol: layers.IPProtocolUDP, - SrcIP: opts.SrcIP.To4(), - DstIP: opts.DstIP.To4(), - } - udp := &layers.UDP{ SrcPort: layers.UDPPort(opts.SrcPort), DstPort: layers.UDPPort(opts.DstPort), } - udp.SetNetworkLayerForChecksum(ip) - payload := opts.Payload if payload == nil { payload = make([]byte, opts.PayloadSize) } + serOpts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true} + + if isIPv6(opts.SrcIP) { + return serializeUDPv6(opts.SrcIP, opts.DstIP, udp, payload, serOpts) + } + return serializeUDPv4(opts.SrcIP, opts.DstIP, udp, payload, serOpts) +} + +func serializeUDPv4(srcIP, dstIP net.IP, udp *layers.UDP, payload []byte, serOpts gopacket.SerializeOptions) []byte { + eth := &layers.Ethernet{SrcMAC: DefaultSrcMAC, DstMAC: DefaultDstMAC, EthernetType: layers.EthernetTypeIPv4} + ip := &layers.IPv4{Version: 4, IHL: 5, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: srcIP.To4(), DstIP: dstIP.To4()} + udp.SetNetworkLayerForChecksum(ip) buf := gopacket.NewSerializeBuffer() - serializeOpts := gopacket.SerializeOptions{ - FixLengths: true, - ComputeChecksums: true, + if err := gopacket.SerializeLayers(buf, serOpts, eth, ip, udp, gopacket.Payload(payload)); err != nil { + panic("failed to serialize UDPv4 packet: " + err.Error()) + } + return buf.Bytes() +} + +func serializeUDPv6(srcIP, dstIP net.IP, udp *layers.UDP, payload []byte, serOpts gopacket.SerializeOptions) []byte { + eth := &layers.Ethernet{SrcMAC: DefaultSrcMAC, DstMAC: DefaultDstMAC, EthernetType: layers.EthernetTypeIPv6} + ip := &layers.IPv6{Version: 6, HopLimit: 64, NextHeader: layers.IPProtocolUDP, SrcIP: srcIP.To16(), DstIP: dstIP.To16()} + udp.SetNetworkLayerForChecksum(ip) + buf := gopacket.NewSerializeBuffer() + if err := gopacket.SerializeLayers(buf, serOpts, eth, ip, udp, gopacket.Payload(payload)); err != nil { + panic("failed to serialize UDPv6 packet: " + err.Error()) } + return buf.Bytes() +} - err := gopacket.SerializeLayers(buf, serializeOpts, - eth, ip, udp, gopacket.Payload(payload)) - if err != nil { - panic("failed to serialize UDP packet: " + err.Error()) +// isIPv6 returns true if ip is an IPv6 address (not IPv4-mapped). +func isIPv6(ip net.IP) bool { + return ip.To4() == nil +} + +// DNSQueryOpts configures a test DNS query packet (Ethernet + IP + UDP + DNS). +type DNSQueryOpts struct { + SrcIP, DstIP net.IP + SrcPort, DstPort uint16 + ID uint16 + Name string + QType layers.DNSType +} + +// BuildDNSQueryPacket constructs a complete Ethernet + IP + UDP + DNS query packet. +// Automatically selects IPv4 or IPv6 based on the source IP address. +func BuildDNSQueryPacket(opts DNSQueryOpts) []byte { + dns := &layers.DNS{ + ID: opts.ID, + RD: true, + QDCount: 1, + Questions: []layers.DNSQuestion{{ + Name: []byte(opts.Name), + Type: opts.QType, + Class: layers.DNSClassIN, + }}, } + return buildDNSPacket(opts.SrcIP, opts.DstIP, opts.SrcPort, opts.DstPort, dns) +} + +// DNSResponseOpts configures a test DNS response packet (Ethernet + IP + UDP + DNS). +type DNSResponseOpts struct { + SrcIP, DstIP net.IP + SrcPort, DstPort uint16 + ID uint16 + Name string + QType layers.DNSType + RCode layers.DNSResponseCode + Answers []net.IP // A/AAAA record answers. +} + +// BuildDNSResponsePacket constructs a complete Ethernet + IP + UDP + DNS response packet. +// Automatically selects IPv4 or IPv6 based on the source IP address. +func BuildDNSResponsePacket(opts DNSResponseOpts) []byte { + dns := &layers.DNS{ + ID: opts.ID, + QR: true, + RD: true, + ResponseCode: opts.RCode, + QDCount: 1, + Questions: []layers.DNSQuestion{{ + Name: []byte(opts.Name), + Type: opts.QType, + Class: layers.DNSClassIN, + }}, + } + for _, ip := range opts.Answers { + rr := layers.DNSResourceRecord{ + Name: []byte(opts.Name), + Type: opts.QType, + Class: layers.DNSClassIN, + TTL: 60, + IP: ip, + } + dns.Answers = append(dns.Answers, rr) + } + dns.ANCount = uint16(len(dns.Answers)) + return buildDNSPacket(opts.SrcIP, opts.DstIP, opts.SrcPort, opts.DstPort, dns) +} +// serializeDNS returns the raw bytes of a DNS layer. +func serializeDNS(dns *layers.DNS) []byte { + buf := gopacket.NewSerializeBuffer() + if err := dns.SerializeTo(buf, gopacket.SerializeOptions{FixLengths: true}); err != nil { + panic("failed to serialize DNS: " + err.Error()) + } return buf.Bytes() } +// buildDNSPacket serializes a DNS layer inside an Ethernet + IP + UDP frame. +func buildDNSPacket(srcIP, dstIP net.IP, srcPort, dstPort uint16, dns *layers.DNS) []byte { + return BuildUDPPacket(UDPPacketOpts{ + SrcIP: srcIP, DstIP: dstIP, SrcPort: srcPort, DstPort: dstPort, + Payload: serializeDNS(dns), + }) +} + +// BuildDNSTCPQueryPacket constructs an Ethernet + IPv4 + TCP packet carrying a +// DNS query. DNS over TCP prepends a 2-byte length field before the message. +func BuildDNSTCPQueryPacket(opts DNSQueryOpts) []byte { + dnsBytes := serializeDNS(&layers.DNS{ + ID: opts.ID, RD: true, QDCount: 1, + Questions: []layers.DNSQuestion{{ + Name: []byte(opts.Name), Type: opts.QType, Class: layers.DNSClassIN, + }}, + }) + tcpPayload := make([]byte, 2+len(dnsBytes)) + tcpPayload[0] = byte(len(dnsBytes) >> 8) + tcpPayload[1] = byte(len(dnsBytes)) + copy(tcpPayload[2:], dnsBytes) + + return BuildTCPPacket(TCPPacketOpts{ + SrcIP: opts.SrcIP, DstIP: opts.DstIP, + SrcPort: opts.SrcPort, DstPort: opts.DstPort, + PSH: true, ACK: true, + Payload: tcpPayload, + }) +} // BuildNonIPPacket constructs an Ethernet frame with the given EtherType and a small payload. // Useful for testing that eBPF programs correctly skip non-IPv4 traffic. diff --git a/pkg/utils/utils_linux.go b/pkg/utils/utils_linux.go index 6aff0d5d2b..3bdd288fbe 100644 --- a/pkg/utils/utils_linux.go +++ b/pkg/utils/utils_linux.go @@ -10,8 +10,9 @@ import ( "syscall" "unsafe" + "errors" + "github.com/cilium/cilium/api/v1/flow" - "github.com/pkg/errors" "github.com/vishvananda/netlink" "golang.org/x/exp/maps" ) @@ -115,6 +116,21 @@ func isDefaultRoute(route netlink.Route) bool { return false } +// GetDefaultIfaceIndex returns the ifindex of the default route interface. +// Returns 0 (all interfaces) if the default route cannot be determined. +var ErrNoDefaultLink = errors.New("no default outgoing link found") + +func GetDefaultIfaceIndex() (int, error) { + links, err := GetDefaultOutgoingLinks() + if err != nil { + return 0, fmt.Errorf("failed to get default outgoing links: %w", err) + } + if len(links) == 0 { + return 0, ErrNoDefaultLink + } + return links[0].Attrs().Index, nil +} + func GetDropReasonDesc(dr DropReason) flow.DropReason { // Set the drop reason. // Retina drop reasons are different from the drop reasons available in flow library. From dfc6bed8119ba2fc2ca1b43f6957aa9c5745cba5 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Fri, 10 Apr 2026 15:22:33 +0100 Subject: [PATCH 296/448] feat(cve-fix): revert Dockerfile builder digests to Go 1.26.1 (#2168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request updates all Dockerfiles in the repository to use newer, more specific, and pinned versions of the Microsoft Go base images. The changes ensure that builds are based on Go 1.26.1 images (with appropriate OS variants), improving reproducibility and consistency across Linux and Windows builds. **Base image updates:** * Updated all Linux-based Dockerfiles to use `mcr.microsoft.com/oss/go/microsoft/golang:1.26.1` or `1.26.1-azurelinux3.0` with the corresponding SHA256 digest for improved version pinning and reproducibility. [[1]](diffhunk://#diff-53fad39439c11209d1fd09c9c8dc733647e91161167f7daf14df477b78f06472L1-R2) [[2]](diffhunk://#diff-fb3f33cdd2a5865385222d244e9bdc9a7ebee2756d506f6495f83a5cff42b25aL1-R2) [[3]](diffhunk://#diff-49752700516c4cf7846baa53e3fcb9f628bff653b0364de4b273f9b900af954aL1-R2) [[4]](diffhunk://#diff-f0dd51cf34c442cdab8226a50e290ac00ab8276c9f8681dc4d8375ec07a8b3acL1-R2) [[5]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L3-R4) [[6]](diffhunk://#diff-105352849a03a69e1cb5f3d40e843034731e66737f833014a4589a6aeee29646L2-R3) [[7]](diffhunk://#diff-6a4f3c9e54acfa9ffd27a142ad70e1a7bb68c5d3d454366569fb2f148ac94993L2-R3) [[8]](diffhunk://#diff-6a4f3c9e54acfa9ffd27a142ad70e1a7bb68c5d3d454366569fb2f148ac94993L19-R20) [[9]](diffhunk://#diff-0793df634d5904e90d444dade524fa1764c63179f1b3cca617f241a0e0711331L1-R2) [[10]](diffhunk://#diff-bc2ff77ba131a806e5fddea1973783d61fdba4e8a33f307a982dca3b29b3956bL1-R2) * Updated all Windows-based Dockerfiles to use `mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022` with the corresponding SHA256 digest for consistent Windows builds. [[1]](diffhunk://#diff-1e96bef04d487cb2a4483d264828b723c73f33f3d8cd86facfd7b979b555b96cL1-R2) [[2]](diffhunk://#diff-909d3861ff2ca17f232d98e86c2bcb422c49017732b04357a88210be028f7f17L6-R7) These updates help ensure that all builds use the same Go toolchain version and OS base, reducing the risk of inconsistencies and unexpected build issues.…ab10de78 Commit c08d8273 inadvertently reverted Go builder image digests from 1.26.1 back to the floating azurelinux3.0 tag (Go 1.24.x). This restores the Go 1.26.1 pinned digests to fix remaining stdlib CVEs (CVE-2026-25679, CVE-2026-27139, CVE-2026-27142) that cannot be fixed on Go 1.24.x. # Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/Dockerfile | 4 ++-- controller/Dockerfile | 4 ++-- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 4 ++-- hack/tools/kapinger/Dockerfile | 8 ++++---- hack/tools/toolbox/Dockerfile | 4 ++-- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2022 | 4 ++-- test/image/Dockerfile | 4 ++-- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 170e9b941a..ad7042741c 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index 1845cd40a4..a56591d69b 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 4b7b32da2e..9dbf6616e4 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 1d3742b774..9f19d9eced 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 6ceebc2e40..85a65f2236 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:a6a40696becc6eae6a673f037349bbdccd4420cccd5c6f9336c71581c1395407 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index e7d33fdb98..c0e3e99513 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:a6a40696becc6eae6a673f037349bbdccd4420cccd5c6f9336c71581c1395407 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 1bb6c10634..f289be43dc 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:latest --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:aa201ad216d45d4e8c8f2512392cc8259c5daa4fa6348973235d715aa2c84c9c AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS builder WORKDIR /build ADD . . @@ -16,8 +16,8 @@ COPY --from=builder /build/kapinger . CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:latest --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:aa201ad216d45d4e8c8f2512392cc8259c5daa4fa6348973235d715aa2c84c9c AS windows-builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS windows-builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 18e8b45980..e321afcc13 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:latest --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:aa201ad216d45d4e8c8f2512392cc8259c5daa4fa6348973235d715aa2c84c9c AS build +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index f4858ca977..2465dcf6bc 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index e152bf061c..2a3e392aaf 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 538a0c60bb..3dbcd13fa8 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:42739e5cb9703e3e0908d0e393ef9e0acde9d7e2ef09edf7b910eda2ebde8eaf AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 5dede2d05b9c6a1bbfb29b5b07395f54c85933b0 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Fri, 10 Apr 2026 17:18:11 +0100 Subject: [PATCH 297/448] chore(deps): update Go base images to version 1.26.2 across multiple dockerfiles (#2179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request updates all Dockerfiles to use newer, patched base images for both Linux and Windows builds. The main changes are version bumps for the Microsoft Go and AzureLinux images, ensuring improved security, stability, and consistency across all build targets. **Base image updates (security and stability):** * All references to `mcr.microsoft.com/oss/go/microsoft/golang` are updated from version `1.26.1` to `1.26.2` with corresponding new digests in every Dockerfile, including for Linux and Windows builds (`cli/Dockerfile`, `controller/Dockerfile`, `controller/Dockerfile.gogen`, `controller/Dockerfile.proto`, `controller/Dockerfile.windows-cgo`, `controller/Dockerfile.windows-native`, `hack/tools/kapinger/Dockerfile`, `hack/tools/toolbox/Dockerfile`, `operator/Dockerfile`, `operator/Dockerfile.windows-2022`, `test/image/Dockerfile`). [[1]](diffhunk://#diff-53fad39439c11209d1fd09c9c8dc733647e91161167f7daf14df477b78f06472L1-R2) [[2]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L3-R10) [[3]](diffhunk://#diff-49752700516c4cf7846baa53e3fcb9f628bff653b0364de4b273f9b900af954aL1-R2) [[4]](diffhunk://#diff-f0dd51cf34c442cdab8226a50e290ac00ab8276c9f8681dc4d8375ec07a8b3acL1-R2) [[5]](diffhunk://#diff-1e96bef04d487cb2a4483d264828b723c73f33f3d8cd86facfd7b979b555b96cL1-R2) [[6]](diffhunk://#diff-909d3861ff2ca17f232d98e86c2bcb422c49017732b04357a88210be028f7f17L6-R7) [[7]](diffhunk://#diff-6a4f3c9e54acfa9ffd27a142ad70e1a7bb68c5d3d454366569fb2f148ac94993L2-R3) [[8]](diffhunk://#diff-6a4f3c9e54acfa9ffd27a142ad70e1a7bb68c5d3d454366569fb2f148ac94993L19-R20) [[9]](diffhunk://#diff-0793df634d5904e90d444dade524fa1764c63179f1b3cca617f241a0e0711331L1-R2) [[10]](diffhunk://#diff-fb3f33cdd2a5865385222d244e9bdc9a7ebee2756d506f6495f83a5cff42b25aL1-R2) [[11]](diffhunk://#diff-bc2ff77ba131a806e5fddea1973783d61fdba4e8a33f307a982dca3b29b3956bL1-R2) [[12]](diffhunk://#diff-105352849a03a69e1cb5f3d40e843034731e66737f833014a4589a6aeee29646L2-R3) * All references to `mcr.microsoft.com/azurelinux/base/core:3.0` and `mcr.microsoft.com/azurelinux/distroless/minimal:3.0` are updated to new digests, ensuring the latest security patches and fixes are used for runtime and distroless images (`cli/Dockerfile`, `controller/Dockerfile`, `operator/Dockerfile`, `shell/Dockerfile`). [[1]](diffhunk://#diff-53fad39439c11209d1fd09c9c8dc733647e91161167f7daf14df477b78f06472L28-R32) [[2]](diffhunk://#diff-53fad39439c11209d1fd09c9c8dc733647e91161167f7daf14df477b78f06472L41-R41) [[3]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L3-R10) [[4]](diffhunk://#diff-df234eb86d676bd9233f232e9dc9af4895969477a6a9ff9161e32621f6ce76d1L113-R113) [[5]](diffhunk://#diff-fb3f33cdd2a5865385222d244e9bdc9a7ebee2756d506f6495f83a5cff42b25aL28-R28) [[6]](diffhunk://#diff-4a6d9372387768fadeba56f4a68cc42504e17293b25abd814bd003cfd6ee3e72L2-R2) No application code or build logic is changed—only the underlying images are updated. This is a best practice for keeping builds secure and reproducible.…Dockerfiles # Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Co-authored-by: Iti Agrawal --- cli/Dockerfile | 10 +++++----- controller/Dockerfile | 10 +++++----- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 4 ++-- hack/tools/kapinger/Dockerfile | 8 ++++---- hack/tools/toolbox/Dockerfile | 4 ++-- operator/Dockerfile | 6 +++--- operator/Dockerfile.windows-2022 | 4 ++-- shell/Dockerfile | 2 +- test/image/Dockerfile | 4 ++-- 12 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index ad7042741c..dfa03a15b9 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,11 +25,11 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # minimal libs stage — provides only the system libraries needed by the CGO-enabled binary, # without the bloat of the full Go SDK image (python, gcc, systemd, etc.) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS libs +FROM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS libs # Target 1: Distroless (secure, minimal) # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b AS distroless-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS distroless-target COPY --from=libs /lib/ /lib COPY --from=libs /usr/lib/ /usr/lib COPY --from=libs /etc/pki/tls/ /etc/pki/tls/ @@ -38,7 +38,7 @@ COPY --from=builder /workspace/kubectl-retina . # Target 2: Shell-enabled (operational, init container support) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS shell-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS shell-target WORKDIR / COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina RUN chmod +x /bin/kubectl-retina diff --git a/controller/Dockerfile b/controller/Dockerfile index a56591d69b..104a9ed064 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,13 +1,13 @@ # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b AS azurelinux-distroless +FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS azurelinux-distroless # build stages @@ -110,7 +110,7 @@ ENTRYPOINT ["./retina/initretina"] # agent final image # mcr.microsoft.com/azurelinux/distroless/minimal:3.0 -# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b +# mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af FROM azurelinux-distroless AS agent COPY --from=tools /lib/ /lib COPY --from=tools /usr/lib/ /usr/lib diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 9dbf6616e4..1ac47bc8f9 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 9f19d9eced..4ebc4430cd 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 85a65f2236..65ac9d60c7 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:3668c2f2d838ebf8d03885e71c6bf309a66b1107a926f0e59c3d9ed1ef150a72 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index c0e3e99513..316828a9b6 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:11f72a416664b71f9891f528fd5fdcb5de51d2c2f3946fa39a0fa549001058e6 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:3668c2f2d838ebf8d03885e71c6bf309a66b1107a926f0e59c3d9ed1ef150a72 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index f289be43dc..ccfb6f3080 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8d219d3f8e6edc46cc6d1f4bec61347560c2bca6ba53c4eae908c542fbc72a65 AS builder WORKDIR /build ADD . . @@ -16,8 +16,8 @@ COPY --from=builder /build/kapinger . CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS windows-builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8d219d3f8e6edc46cc6d1f4bec61347560c2bca6ba53c4eae908c542fbc72a65 AS windows-builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index e321afcc13..3609abbd06 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:4650f4a1d3e9bcd39aa39df373837a7fe3f2d0ef75ce2836d1e8e44249c03e82 AS build +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8d219d3f8e6edc46cc6d1f4bec61347560c2bca6ba53c4eae908c542fbc72a65 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 2465dcf6bc..691fa19903 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,7 +25,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ ##################### controller ####################### # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:22810fd97d6ad5ec7d5bdd5b00233a3050be01d9e26b47b16cb6f1a7f178834b +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 2a3e392aaf..dcb0a5a778 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder # Build args ARG VERSION diff --git a/shell/Dockerfile b/shell/Dockerfile index 65070649a1..c885460ef2 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:a452d39c91576f5a2c983c7d3b62521fabd08e16b4a7237e24bf2be3b06e1651 +FROM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b RUN tdnf install -y \ bind-utils \ diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 3dbcd13fa8..f3847464af 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.1-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:7fbb3de047ac3df460e7f24cacf8ef70eb120b515dce2628e6ad8cc9ea2ce2be AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 304e851b30e905084eecd2b4da588c1755c64c98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:01:08 -0400 Subject: [PATCH 298/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.8.6 to 0.16.0 (#2175) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.8.6 to 0.16.0.
Commits
  • 567d0ad build(deps): bump the all group in /pkg/azclient with 2 updates (#10150)
  • 40031ed build(deps): bump the all group with 2 updates (#10152)
  • 6fd1a70 build(deps): bump github.com/go-git/go-git/v5 (#10149)
  • 416612e Merge pull request #10148 from kubernetes-sigs/feat/allow-cross-tenant-replic...
  • 80ef90c test: clarify test comments to reflect nil=don't care semantics
  • aeb2ad9 address review: nil means don't care, fix struct alignment
  • 9025a99 test: add unit tests for isAllowCrossTenantReplicationEqual
  • ff77107 feat: support AllowCrossTenantReplication in AccountOptions
  • 84bacac Merge pull request #10132 from nilo19/fix/cve-otel-grpc-master
  • 16f956a chore: remove stale go.sum entries from platform-specific tidy
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.8.6&new-version=0.16.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 68 +++++++++++----------------- go.sum | 139 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 95 insertions(+), 112 deletions(-) diff --git a/go.mod b/go.mod index 713552ed51..3d0a38e1b9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/microsoft/retina -go 1.24.11 +go 1.25.0 require ( github.com/go-chi/chi/v5 v5.2.4 @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.10.1 go.uber.org/zap v1.27.0 k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 ) @@ -22,7 +22,6 @@ require ( cel.dev/expr v0.25.1 // indirect code.cloudfoundry.org/clock v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0 // indirect @@ -37,7 +36,7 @@ require ( github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -70,11 +69,8 @@ require ( github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/containerd v1.7.29 // indirect - github.com/containerd/continuity v0.4.4 // indirect github.com/containerd/errdefs v0.3.0 // indirect - github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/containerd/ttrpc v1.2.7 // indirect github.com/containerd/typeurl/v2 v2.2.0 // indirect github.com/containernetworking/cni v1.2.3 // indirect github.com/coreos/go-semver v0.3.1 // indirect @@ -87,7 +83,6 @@ require ( github.com/docker/docker v28.5.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect @@ -158,10 +153,6 @@ require ( github.com/moby/locker v1.0.1 // indirect github.com/moby/moby v26.1.0+incompatible // indirect github.com/moby/spdystream v0.5.0 // indirect - github.com/moby/sys/mountinfo v0.7.1 // indirect - github.com/moby/sys/sequential v0.6.0 // indirect - github.com/moby/sys/signal v0.7.0 // indirect - github.com/moby/sys/user v0.3.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -169,8 +160,6 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/opencontainers/runtime-spec v1.2.0 // indirect - github.com/opencontainers/selinux v1.13.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.2-0.20180312054125-0646ccaebea1+incompatible // indirect @@ -180,7 +169,6 @@ require ( github.com/prometheus/procfs v0.16.1 // indirect github.com/rubenv/sql-migrate v1.7.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/shopspring/decimal v1.4.0 // indirect @@ -208,11 +196,11 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/mod v0.31.0 - golang.org/x/text v0.33.0 // indirect - golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.40.0 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/mod v0.33.0 + golang.org/x/text v0.35.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.42.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 // indirect @@ -220,7 +208,6 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/apiserver v0.32.3 // indirect k8s.io/component-base v0.32.3 // indirect - k8s.io/cri-api v0.30.1 // indirect oras.land/oras-go v1.2.5 // indirect sigs.k8s.io/kustomize/api v0.18.0 // indirect sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect @@ -239,18 +226,18 @@ require ( github.com/spf13/pflag v1.0.9 github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.49.0 // indirect + golang.org/x/net v0.52.0 // indirect golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sync v0.19.0 - golang.org/x/sys v0.40.0 - golang.org/x/term v0.39.0 // indirect + golang.org/x/sync v0.20.0 + golang.org/x/sys v0.42.0 + golang.org/x/term v0.41.0 // indirect google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.4 k8s.io/apimachinery v0.32.4 - k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect - k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/yaml v1.6.0 @@ -259,8 +246,8 @@ require ( require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 @@ -292,8 +279,8 @@ require ( github.com/mdlayher/netlink v1.8.0 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.0 - github.com/onsi/ginkgo/v2 v2.25.3 - github.com/onsi/gomega v1.38.2 + github.com/onsi/ginkgo/v2 v2.28.1 + github.com/onsi/gomega v1.39.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.67.5 @@ -301,10 +288,10 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.1 github.com/vishvananda/netlink v1.3.1 - go.opentelemetry.io/otel v1.40.0 - go.opentelemetry.io/otel/metric v1.40.0 - go.opentelemetry.io/otel/trace v1.40.0 - go.uber.org/mock v0.5.2 + go.opentelemetry.io/otel v1.43.0 + go.opentelemetry.io/otel/metric v1.43.0 + go.opentelemetry.io/otel/trace v1.43.0 + go.uber.org/mock v0.6.0 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 google.golang.org/grpc v1.80.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 @@ -322,12 +309,10 @@ require ( require ( github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/cilium/statedb v0.3.7 - github.com/containerd/containerd/api v1.8.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/google/cel-go v0.24.1 // indirect - github.com/moby/sys/userns v0.1.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect ) @@ -353,10 +338,11 @@ require ( github.com/Antonboom/testifylint v1.5.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.6.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v9 v9.0.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v2 v2.0.0 // indirect github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect @@ -474,7 +460,7 @@ require ( github.com/google/go-github/v62 v62.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/ko v0.15.4 // indirect - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect diff --git a/go.sum b/go.sum index 965dc6f188..30473b9777 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,6 @@ github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgB github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= @@ -57,10 +55,10 @@ github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiX github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 h1:MhRfI58HblXzCtWEZCO0feHs8LweePB3s90r7WaR1KU= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0/go.mod h1:okZ+ZURbArNdlJ+ptXoyHNuOETzOl1Oww19rm8I2WLA= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= @@ -71,8 +69,8 @@ github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGlu github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 h1:Hp+EScFOu9HeCbeW8WU2yQPJd4gGwhMgKxWe+G6jNzw= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0/go.mod h1:/pz8dyNQe+Ey3yBp/XuYz7oqX8YDNWVpPB0hH3XWfbc= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.4.0 h1:z7Mqz6l0EFH549GvHEqfjKvi+cRScxLWbaoeLm9wxVQ= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.4.0/go.mod h1:v6gbfH+7DG7xH2kUNs+ZJ9tF6O3iNnR85wMtmr+F54o= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0 h1:nyxugFxG2uhbMeJVCFFuD2j9wu+6KgeabITdINraQsE= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0/go.mod h1:e4RAYykLIz73CF52KhSooo4whZGXvXrD09m0jkgnWiU= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0 h1:DWlwvVV5r/Wy1561nZ3wrpI1/vDIBRY/Wd1HWaRBZWA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0/go.mod h1:E7ltexgRDmeJ0fJWv0D/HLwY2xbDdN+uv+X2uZtOx3w= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 h1:0nGmzwBv5ougvzfGPCO2ljFRHvun57KpNrVCMrlk0ns= @@ -95,20 +93,22 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanage github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 h1:Ds0KRF8ggpEGg4Vo42oX1cIt/IfOhHWJBikksZbVxeg= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0/go.mod h1:jj6P8ybImR+5topJ+eH6fgcemSFBmU6/6bFF8KkwuDI= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0 h1:z4YeiSXxnUI+PqB46Yj6MZA3nwb1CcJIkEMDrzUd8Cs= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0/go.mod h1:rko9SzMxcMk0NJsNAxALEGaTYyy79bNRwxgJfrH0Spw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0 h1:L7G3dExHBgUxsO3qpTGhk/P2dgnYyW48yn7AO33Tbek= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0/go.mod h1:Ms6gYEy0+A2knfKrwdatsggTXYA2+ICKug8w7STorFw= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 h1:qBlqTo40ARdI7Pmq+enBiTnejZk2BF+PHgktgG8k3r8= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0/go.mod h1:UmyOatRyQodVpp55Jr5WJmnkmVW4wKfo85uHFmMEjfM= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0 h1:HYGD75g0bQ3VO/Omedm54v4LrD3B1cGImuRF3AJ5wLo= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0/go.mod h1:ulHyBFJOI0ONiRL4vcJTmS7rx18jQQlEPmAgo80cRdM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v9 v9.0.0 h1:CbHDMVJhcJSmXenq+UDWyIjumzVkZIb5pVUGzsCok5M= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v9 v9.0.0/go.mod h1:raqbEXrok4aycS74XoU6p9Hne1dliAFpHLizlp+qJoM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 h1:yzrctSl9GMIQ5lHu7jc8olOsGjWDCsBpJhWqfGa/YIM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0/go.mod h1:GE4m0rnnfwLGX0Y9A9A25Zx5N/90jneT5ABevqzhuFQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v2 v2.0.0 h1:+vh02EiRx2UmL9NDoA36U18Bgwl9luxs6ia0GAI9Rzg= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v2 v2.0.0/go.mod h1:iKOtU3WyuNvNc4L1Z4IxHaoO0dGq5tg+uhLix/KRmzE= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S6wk65vfC6m3FIxJ+i5QDyN9JWwXI8Hb0Img10hU= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= @@ -148,8 +148,8 @@ github.com/Azure/perf-tests/network/benchmarks/netperf v0.0.0-20241008140716-395 github.com/Azure/perf-tests/network/benchmarks/netperf v0.0.0-20241008140716-395a79947d2c/go.mod h1:jeV6A8q9uDVDwffTt5KBk+5g7bXfpEImYW6qLKn0E+I= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= @@ -420,24 +420,18 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE= github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs= -github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= -github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= github.com/containerd/errdefs v0.3.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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= -github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= -github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= @@ -571,6 +565,12 @@ github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYF github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/github/smimesign v0.2.0 h1:Hho4YcX5N1I9XNqhq0fNx0Sts8MhLonHd+HRXVGNjvk= github.com/github/smimesign v0.2.0/go.mod h1:iZiiwNT4HbtGRVqCQu7uJPEZCuEE5sfSSttcnePkDl4= +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/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= @@ -581,8 +581,8 @@ github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-faker/faker/v4 v4.6.1 h1:xUyVpAjEtB04l6XFY0V/29oR332rOSPWV4lU8RwDt4k= -github.com/go-faker/faker/v4 v4.6.1/go.mod h1:arSdxNCSt7mOhdk8tEolvHeIJ7eX4OX80wXjKKvkKBY= +github.com/go-faker/faker/v4 v4.7.0 h1:VboC02cXHl/NuQh5lM2W8b87yp4iFXIu59x4w0RZi4E= +github.com/go-faker/faker/v4 v4.7.0/go.mod h1:u1dIRP5neLB6kTzgyVjdBOV5R1uP7BdxkcWk7tiKQXk= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -670,6 +670,8 @@ github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4 github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -769,8 +771,8 @@ github.com/google/ko v0.15.4 h1:0blRbIdPmSy6v4LvedGxbI/8krdJYQgbSih3v6Y8V1c= github.com/google/ko v0.15.4/go.mod h1:ZkcmfV91Xt6ZzOBHc/cXXGYnqWdNWDVy/gHoUU9sjag= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= @@ -932,6 +934,8 @@ github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/rasw github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +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/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= @@ -1028,6 +1032,8 @@ github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +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/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= @@ -1072,6 +1078,8 @@ github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/ github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= +github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= +github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= @@ -1106,8 +1114,6 @@ github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStA github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= 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/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= -github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= @@ -1183,23 +1189,19 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw= -github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE= +github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= +github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= 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.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runc v1.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19oYB80= github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM= -github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= -github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE= -github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -1299,8 +1301,6 @@ github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= -github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a h1:np2nR32/A/VcOG9Hn+IOPA8kMk1gbBzK5LpSsgq5pJI= -github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a/go.mod h1:wiP6GQ2T378F+YIyuNw7yXtBxJZR+fqrrn1Z6UHZi0Q= github.com/safchain/ethtool v0.7.0 h1:rlJzfDetsVvT61uz8x1YIcFn12akMfuPulHtZjtb7Is= github.com/safchain/ethtool v0.7.0/go.mod h1:MenQKEjXdfkjD3mp2QdCk8B/hwvkrlOTm/FD4gTpFxQ= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= @@ -1529,8 +1529,8 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= -go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +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/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= @@ -1555,16 +1555,16 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgT go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDTe3Y= go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= -go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= -go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +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.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= -go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= -go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= +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 v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= @@ -1580,8 +1580,8 @@ go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -1617,8 +1617,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -1645,8 +1645,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= -golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1685,8 +1685,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= @@ -1704,8 +1704,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -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/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1748,7 +1748,6 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1769,8 +1768,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1781,8 +1780,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1794,10 +1793,10 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1829,8 +1828,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= -golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -1947,18 +1946,16 @@ k8s.io/client-go v0.32.4 h1:zaGJS7xoYOYumoWIFXlcVrsiYioRPrXGO7dBfVC5R6M= k8s.io/client-go v0.32.4/go.mod h1:k0jftcyYnEtwlFW92xC7MTtFv5BNcZBr+zn9jPlT9Ic= k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= -k8s.io/cri-api v0.30.1 h1:AUM78wiC56B1WJ2c795AS0IG5T57CkEdkn0IuC+miAE= -k8s.io/cri-api v0.30.1/go.mod h1://4/umPJSW1ISNSNng4OwjpkvswJOQwU8rnkvO8P+xg= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI= k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg= k8s.io/metrics v0.32.3 h1:2vsBvw0v8rIIlczZ/lZ8Kcqk9tR6Fks9h+dtFNbc2a4= k8s.io/metrics v0.32.3/go.mod h1:9R1Wk5cb+qJpCQon9h52mgkVCcFeYxcY+YkumfwHVCU= -k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro= -k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= @@ -1967,8 +1964,8 @@ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6 h1:eihqzFmOkaHB27UsvaGrP4FBH1q00rUwNCEedmu8S+4= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.8.6/go.mod h1:4OImMMFi7wMfpcUcVrUvXO46mi21ndTTuRtQGzuEMD4= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0 h1:gw3Xs5UzvvkhL8OEp1FF2AdHST3nNvWNjxZ6raSOD6w= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0/go.mod h1:JtYQ5YsO3jVngwsQktrm+gCB43BrQ3tPAS1YyooPxhs= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= From 0e2aa1a4afa9058262fc2fc082e714e3e33ce327 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:46:45 -0400 Subject: [PATCH 299/448] deps: bump github.com/mdlayher/netlink from 1.8.0 to 1.10.0 (#2171) Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.8.0 to 1.10.0.
Release notes

Sourced from github.com/mdlayher/netlink's releases.

v1.10.0

See https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md#v1100

v1.9.0

See https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md#v190.

Changelog

Sourced from github.com/mdlayher/netlink's changelog.

v1.10.0

  • [New API]: #270 added MessageBufferSize option to netlink.Config for configuring the size of the copy buffer used for receiving messages. This can improve performance in high-throughput applications by reducing the number of syscalls needed to receive messages.
  • [Improvement]: #219 added debug logging inspired by libmnl. This is now the new default when setting NLDEBUG in the environment.
  • [New API]: #258 added netlink.Conn.ReceiveIter for iterating over responses without collecting them into a slice. It also optimized netlink.Conn.Receive to use this new API internally so that less memory is used.
  • [Improvement]: #269 made it so nltest.Conn.Receive can be used to test that multi-part messages are drained properly.
  • [Improvement]: #266 optimized the initial parsing of netlink messages in netlink.Socket.Receive by adding an iterator for parsing messages directly from the receive buffer.
  • [Improvement]: #267 added integration test benchmarks for multi-part dumps.
  • [Improvement]: #215 optimized the internal peek/allocate logic in netlink.Socket.Receive. Messages are no longer being copied during peeking and the buffer is allocated to the exact size of the upcoming message.
  • [Bug Fix]: #265 fixed a bug where concurrent calls to netlink.Conn.Receive could race with each other when handling multi-part messages. Calls to Receive are now serialized.
  • [Improvement]: #264 added handling for truncated messages in netlink.Socket.Receive.

v1.9.0

This is the first release of package netlink that only supports Go 1.24+.

  • [Improvement]: updated dependencies and Go version to 1.24; tests now run on Go 1.24-1.26.
  • [New API]: #236 introduced Sequence field to OpError for better error correlation.
  • [New API]: #237 added netlink.Conn.PID method to retrieve the connection's PID, also known as port ID.
  • [Improvement]: #228 fixed skipping of specific tests on big-endian hosts.
Commits
  • 0d93d86 CHANGELOG: release v1.10.0 (#271)
  • 6d8d9ce netlink: add MessageBufferSize configuration option (#270)
  • 5c0c409 debug: option to print using mnl format (#219)
  • 758d46d build(deps): bump actions/setup-go from 6.2.0 to 6.3.0 (#263)
  • 5af0e4f netlink, nltest: add ReceiveIter to stream responses (#258)
  • ccabe8e nltest: split multi-part messages into smaller batches (#269)
  • 2a932c0 netlink: add parseMessagesIter to reduce memory usage (#266)
  • a51a734 internal/integration: add benchmark for multi-part netlink dumps (#267)
  • dce357b conn: reduce initial memory in Receive() (#215)
  • 596ce22 conn_linux: serialize Receive calls (#265)
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3d0a38e1b9..e9424f3b64 100644 --- a/go.mod +++ b/go.mod @@ -276,7 +276,7 @@ require ( github.com/inspektor-gadget/inspektor-gadget v0.27.0 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 - github.com/mdlayher/netlink v1.8.0 + github.com/mdlayher/netlink v1.10.0 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.0 github.com/onsi/ginkgo/v2 v2.28.1 diff --git a/go.sum b/go.sum index 30473b9777..86a4cdb65e 100644 --- a/go.sum +++ b/go.sum @@ -1072,8 +1072,8 @@ github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuri github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= -github.com/mdlayher/netlink v1.8.0 h1:e7XNIYJKD7hUct3Px04RuIGJbBxy1/c4nX7D5YyvvlM= -github.com/mdlayher/netlink v1.8.0/go.mod h1:UhgKXUlDQhzb09DrCl2GuRNEglHmhYoWAHid9HK3594= +github.com/mdlayher/netlink v1.10.0 h1:K7NHm0iQh2nOtfsj/YNNSN1s7T5JGtNCNwP66OKNiEw= +github.com/mdlayher/netlink v1.10.0/go.mod h1:YBnl5BXsCoRuwBjKKlZ+aYmEoq0r12FDA/3JC+94KDg= github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= From fa619ab9a93c65ff15ddde8b9552dfffcf548623 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 18:13:02 -0400 Subject: [PATCH 300/448] deps: bump docker/build-push-action from 7.0.0 to 7.1.0 (#2170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 7.0.0 to 7.1.0.
Release notes

Sourced from docker/build-push-action's releases.

v7.1.0

Full Changelog: https://github.com/docker/build-push-action/compare/v7.0.0...v7.1.0

Commits
  • bcafcac Merge pull request #1509 from docker/dependabot/npm_and_yarn/vite-7.3.2
  • 18e62f1 Merge pull request #1510 from docker/dependabot/npm_and_yarn/lodash-4.18.1
  • 46580d2 chore: update generated content
  • 3f80b25 chore(deps): Bump lodash from 4.17.23 to 4.18.1
  • efeec95 Merge pull request #1505 from crazy-max/refactor-git-context
  • ddf04b0 Merge pull request #1511 from docker/dependabot/github_actions/crazy-max-dot-...
  • db08d97 chore(deps): Bump the crazy-max-dot-github group with 2 updates
  • ef1fb96 Merge pull request #1508 from docker/dependabot/github_actions/docker/login-a...
  • 2d8f2a1 chore: update generated content
  • 919ac7b fix test since secrets are not written to temp path anymore
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/build-push-action&package-manager=github_actions&previous-version=7.0.0&new-version=7.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/kapinger.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 159872ff8c..56034e450f 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -52,7 +52,7 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Linux Kapinger Image - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -73,7 +73,7 @@ jobs: - name: Push Linux Kapinger Image if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -103,7 +103,7 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Windows Kapinger Image - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -166,7 +166,7 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build Linux Toolbox Image - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: context: hack/tools file: hack/tools/toolbox/Dockerfile From c74105caf5696f0ea6aa2d4e2b9994813fab4e89 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Sun, 12 Apr 2026 13:10:59 -0400 Subject: [PATCH 301/448] feat: add kernel version to telemetry traces (#2164) ## Summary Adds kernel version to the base `TelemetryClient` properties. Before this, only heartbeat events included the kernel version. Now all `TrackTrace`, `TrackEvent`, and `TrackMetric` calls include it. ## Why this matters Issue #1071 asks for kernel version on traces to directly identify which kernel produces a specific log. The heartbeat already fetches it via `KernelVersion()` at `telemetry.go:170`. This change calls the same function during client initialization so the property is on every telemetry item. ## Changes - `pkg/telemetry/telemetry.go`: Call `KernelVersion(context.Background())` in `NewAppInsightsTelemetryClient` and store in the base properties map. ## Testing - Verified Go compilation passes for `./pkg/telemetry/...` Fixes #1071 This contribution was developed with AI assistance (Claude Code). Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> --- pkg/telemetry/telemetry.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index 0cedef23aa..abbd3a22f4 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -105,6 +105,13 @@ func NewAppInsightsTelemetryClient(processName string, additionalproperties map[ properties := GetEnvironmentProperties() + kernelVer, err := KernelVersion(context.Background()) + if err != nil { + fmt.Printf("failed to get kernel version for telemetry properties: %v\n", err) + } else { + properties[kernelversion] = kernelVer + } + for k, v := range additionalproperties { properties[k] = v } From b9d970bde9fad978fe46528a43e87480e25ff0f0 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 13 Apr 2026 10:43:46 -0400 Subject: [PATCH 302/448] fix(ci): reorder buildx setup before GHCR login in kapinger workflow (#2142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Currently, `docker login ghcr.io` runs before `docker/setup-buildx-action` in all kapinger workflow jobs. When buildx bootstraps, it pulls `moby/buildkit:buildx-stable-1` from Docker Hub — but the prior GHCR login poisons the Docker credential store, causing a 401 against `registry-1.docker.io`. This PR reorders all 4 jobs (`build-linux`, `build-windows`, `manifest`, `build-toolbox`) to run `Set up Docker Buildx` before `Log in to GHCR`, so buildx can pull its builder image from Docker Hub with no credentials configured. Failed run: https://github.com/microsoft/retina/actions/runs/23654791759/job/68908997696 ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. (not applicable — CI-only change) - [ ] I have added tests, if applicable. (not applicable — CI-only change) ## Screenshots (if applicable) or Testing Completed CI will validate — the workflow triggers on PRs that touch `.github/workflows/kapinger.yaml`. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- .github/workflows/kapinger.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 56034e450f..6d6a1710fb 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -44,13 +44,13 @@ jobs: id: vars run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - name: Log in to GHCR if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - name: Build Linux Kapinger Image uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: @@ -95,13 +95,13 @@ jobs: id: vars run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - name: Log in to GHCR if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - name: Build Windows Kapinger Image uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: @@ -127,12 +127,12 @@ jobs: id: vars run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - name: Log in to GHCR - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - name: Log in to GHCR + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + - name: Create and push manifest run: | TAG=${{ steps.vars.outputs.sha_short }} @@ -158,13 +158,13 @@ jobs: id: vars run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - name: Log in to GHCR if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - name: Build Linux Toolbox Image uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: From e1e4c6319d4ad0570d17923e51a02af10fd4a8fc Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 13 Apr 2026 10:46:31 -0400 Subject: [PATCH 303/448] fix(ci): run perf tests only after E2E passes (#2185) # Description Currently `perf-test-basic` and `perf-test-advanced` in `images.yaml` run in parallel with the `e2e` job. If E2E is already failing, both perf jobs still spin up AKS clusters, wasting ~2 hours of compute and 2 additional resource groups. This adds `e2e` to the `needs` list for both perf jobs so they only run after E2E passes. ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Workflow-only change. Verified YAML syntax is correct. ## Additional Notes N/A Signed-off-by: Quang Nguyen --- .github/workflows/images.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 4765af92e1..0ba2aa5775 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -427,7 +427,7 @@ jobs: perf-test-basic: if: ${{ github.event_name == 'merge_group'}} - needs: [manifests, get-tag] + needs: [manifests, get-tag, e2e] uses: ./.github/workflows/perf-template.yaml with: image-registry: ${{ vars.ACR_NAME }} @@ -443,7 +443,7 @@ jobs: perf-test-advanced: if: ${{ github.event_name == 'merge_group'}} - needs: [manifests, get-tag] + needs: [manifests, get-tag, e2e] uses: ./.github/workflows/perf-template.yaml with: image-registry: ${{ vars.ACR_NAME }} From b14cb8634580440d467c5b201878391285267819 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Mon, 13 Apr 2026 16:05:56 +0100 Subject: [PATCH 304/448] feat(deps): update aws-sdk-go-v2 and related dependencies to latest versions (#2183) This pull request updates several AWS SDK for Go dependencies and related indirect dependencies in the `go.mod` file to newer versions. The main goal is to keep the project up-to-date with the latest bug fixes and improvements from upstream libraries. Dependency updates: * AWS SDK for Go core and service packages have been updated to newer versions, including `aws-sdk-go-v2` (from v1.41.1 to v1.41.5) and `aws-sdk-go-v2/service/s3` (from v1.93.0 to v1.99.0). * Several AWS SDK for Go indirect dependencies have been updated, such as `aws/protocol/eventstream`, `internal/configsources`, `internal/endpoints/v2`, `internal/v4a`, `service/internal/accept-encoding`, `service/internal/checksum`, `service/internal/presigned-url`, `service/internal/s3shared`, and `smithy-go`. * The `go-jose/go-jose/v4` cryptography library has been updated from v4.1.3 to v4.1.4.# Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- go.mod | 24 ++++++++++++------------ go.sum | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index e9424f3b64..b1121eb158 100644 --- a/go.mod +++ b/go.mod @@ -45,20 +45,20 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect - github.com/aws/smithy-go v1.24.0 // indirect + github.com/aws/smithy-go v1.24.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -258,10 +258,10 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Microsoft/hcsshim v0.13.0 github.com/Sytten/logrus-zap-hook v0.1.0 - github.com/aws/aws-sdk-go-v2 v1.41.1 + github.com/aws/aws-sdk-go-v2 v1.41.5 github.com/aws/aws-sdk-go-v2/config v1.31.6 github.com/aws/aws-sdk-go-v2/credentials v1.19.7 - github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.18.0-pre.1 github.com/cilium/ebpf v0.18.0 @@ -311,7 +311,7 @@ require ( github.com/cilium/statedb v0.3.7 github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/go-jose/go-jose/v4 v4.1.3 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/google/cel-go v0.24.1 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 86a4cdb65e..76ee727a67 100644 --- a/go.sum +++ b/go.sum @@ -244,10 +244,10 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= -github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= +github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= +github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ= github.com/aws/aws-sdk-go-v2/credentials v1.19.7 h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8= @@ -256,38 +256,38 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBc github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 h1:NLYTEyZmVZo0Qh183sC8nC+ydJXOOeIL/qI/sS3PdLY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15/go.mod h1:Z803iB3B0bc8oJV8zH2PERLRfQUJ2n2BXISpsA4+O1M= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 h1:P1MU/SuhadGvg2jtviDXPEejU3jBNhoeeAlRadHzvHI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6/go.mod h1:5KYaMG6wmVKMFBSfWoyG/zH8pWwzQFnKgpoSRlXHKdQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 h1:wsSQ4SVz5YE1crz0Ap7VBZrV4nNqZt4CIBBT8mnwoNc= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15/go.mod h1:I7sditnFGtYMIqPRU1QoHZAUrXkGp4SczmlLwrNPlD0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 h1:IrbE3B8O9pm3lsg96AXIN5MXX4pECEuExh/A0Du3AuI= -github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0/go.mod h1:/sJLzHtiiZvs6C1RbxS/anSAFwZD6oC6M/kotQzOiLw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= +github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk= github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 h1:gd84Omyu9JLriJVCbGApcLzVR3XtmC4ZDPcAI6Ftvds= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= -github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= -github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f/go.mod h1:rAE739ssmE5O5fLuQ2y8uHdmOJaelE5I0Es3SxV0y1A= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= @@ -595,8 +595,8 @@ github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= -github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= From a08cc3d092eb52dc213154f92bb587fd40cbd410 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:05:01 +0000 Subject: [PATCH 305/448] deps: bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (#2187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 4.0.0 to 5.0.0.
Release notes

Sourced from actions/upload-pages-artifact's releases.

v5.0.0

Changelog

See details of all code changes since previous release.

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-pages-artifact&package-manager=github_actions&previous-version=4.0.0&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index f050d5e00d..750ca96c3d 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -36,7 +36,7 @@ jobs: npm run build --prefix site/ - name: Upload build artifact if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: "./site/build" From c2e90b2d9f2522858ea54c53ced435a75fb30c88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:05:24 +0000 Subject: [PATCH 306/448] deps: bump actions/upload-artifact from 7.0.0 to 7.0.1 (#2186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.
Release notes

Sourced from actions/upload-artifact's releases.

v7.0.1

What's Changed

Full Changelog: https://github.com/actions/upload-artifact/compare/v7...v7.0.1

Commits
  • 043fb46 Merge pull request #797 from actions/yacaovsnc/update-dependency
  • 634250c Include changes in typespec/ts-http-runtime 0.3.5
  • e454baa Readme: bump all the example versions to v7 (#796)
  • 74fad66 Update the readme with direct upload details (#795)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=7.0.0&new-version=7.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- .github/workflows/release-images.yaml | 2 +- .github/workflows/test.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 0ba2aa5775..1bc0a56adf 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -110,7 +110,7 @@ jobs: APP_INSIGHTS_ID: ${{ secrets.AZURE_APP_INSIGHTS_KEY }} - name: Upload Windows Binaries - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index ea25908a25..d5a8a653e7 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -86,7 +86,7 @@ jobs: TAG=$TAG - name: Upload Windows Binaries - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: windows-binaries path: output/windows_amd64/ diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8f836a9019..1d8d2fd454 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -37,7 +37,7 @@ jobs: make test-image IMAGE_NAMESPACE=${{ github.repository }} PLATFORM=linux/amd64 - name: Upload Artifacts - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage-files path: ./artifacts/coverage* From 584cd303afe02867e149f1d8142b1e8f864de474 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 13 Apr 2026 12:15:43 -0400 Subject: [PATCH 307/448] fix(ci): prevent resource group leaks from cancelled E2E/perf workflows (#2184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description `images.yaml` sets `cancel-in-progress: true`, so when the merge queue re-checks the same ref, GitHub cancels the in-progress run. The runner sends SIGTERM to the Go test process, which gets killed before `t.Cleanup()` fires — orphaning the Azure resource group. Each merge queue run creates 3 RGs (E2E, perf-basic, perf-advanced), so a single cancellation leaks 3 clusters. The second issue is that `CLUSTER_NAME` is generated inside Go code using a Unix timestamp, making it unknowable to the workflow. Without knowing the name, no external cleanup is possible. This PR fixes both: - **Naming**: Set `CLUSTER_NAME` deterministically at job level using `github.run_id` + `github.run_attempt`, so both the test step and cleanup step share the same name - **Cleanup**: Add `if: always()` cleanup step to `e2e.yaml`, `images.yaml`, and `perf-template.yaml` that checks `az group exists` and deletes the RG if it's still around The cleanup step is a no-op when the test already cleaned up (the `az group exists` check returns false), and runs even after workflow cancellation since GitHub executes `if: always()` steps after sending SIGKILL. ## Related Issue N/A — found during investigation of 12 leaked `runner-e2e-netobs-*` RGs consuming all 96 DPDSv5 cores in the test subscription. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Verified root cause by correlating leaked RG timestamps with CI run logs: - **Cancelled run `24145596870`** (Apr 8): E2E + perf-basic + perf-advanced all created RGs (`-1775665227`, `-1775665233`, `-1775665236`), cancelled at 16:21:50, no cleanup ran — all 3 in leaked list - **Successful run `24311965309`** (Apr 12): 3 RGs created, all 3 deleted via `t.Cleanup()` — none in leaked list The `if: always()` + `az group exists` pattern is well-established in GitHub Actions for exactly this failure mode. ## Additional Notes The existing `t.Cleanup()` in Go test code still runs on normal test completion (success or failure). This workflow-level cleanup is a safety net for the cancellation path only. Signed-off-by: Quang Nguyen --- .github/workflows/e2e.yaml | 12 +++++++++++- .github/workflows/images.yaml | 11 +++++++++++ .github/workflows/perf-template.yaml | 15 +++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 769992b03b..f35c2841fb 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -84,6 +84,8 @@ jobs: name: E2E runs-on: ubuntu-latest timeout-minutes: 120 + env: + CLUSTER_NAME: retina-e2e-${{ github.run_id }}-${{ github.run_attempt }} steps: - name: Checkout code @@ -116,4 +118,12 @@ jobs: fi go test -v ./test/e2e/. -timeout 60m -tags=e2e -count=1 -args -image-tag=${{ inputs.image_tag }} -image-registry=${{ inputs.image_registry }} -image-namespace=${{ inputs.image_namespace }} -create-infra=${{ !inputs.use_existing_infra }} -delete-infra=${{ !inputs.use_existing_infra }} - \ No newline at end of file + + - name: Cleanup resource group + if: always() + shell: bash + run: | + if az group exists --name "$CLUSTER_NAME" 2>/dev/null | grep -q true; then + echo "Deleting resource group $CLUSTER_NAME..." + az group delete --name "$CLUSTER_NAME" --yes --no-wait || true + fi diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 1bc0a56adf..f62ce76412 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -397,6 +397,8 @@ jobs: needs: [manifests] runs-on: ubuntu-latest timeout-minutes: 90 + env: + CLUSTER_NAME: retina-e2e-${{ github.run_id }}-${{ github.run_attempt }} steps: - name: Checkout code @@ -425,6 +427,15 @@ jobs: set -euo pipefail go test -v ./test/e2e/. -timeout 60m -tags=e2e -count=1 -args -image-tag=$(make version) -image-registry=${{ vars.ACR_NAME }} -image-namespace=${{ github.repository}} + - name: Cleanup resource group + if: always() + shell: bash + run: | + if az group exists --name "$CLUSTER_NAME" 2>/dev/null | grep -q true; then + echo "Deleting resource group $CLUSTER_NAME..." + az group delete --name "$CLUSTER_NAME" --yes --no-wait || true + fi + perf-test-basic: if: ${{ github.event_name == 'merge_group'}} needs: [manifests, get-tag, e2e] diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index 9929072e36..f232d9e932 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -47,6 +47,8 @@ jobs: name: Retina ${{ inputs.retina-mode }} Performance Test runs-on: ubuntu-latest timeout-minutes: 150 + env: + CLUSTER_NAME: retina-perf-${{ inputs.retina-mode }}-${{ github.run_id }}-${{ github.run_attempt }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -72,11 +74,20 @@ jobs: shell: bash run: | set -euo pipefail - + TAG="${{ inputs.tag }}" REGISTRY="${{ inputs.image-registry }}" NAMESPACE="${{ inputs.image-namespace }}" MODE="${{ inputs.retina-mode }}" - + echo "Running in $MODE mode..." go test -v ./test/e2e/. -timeout 2h -tags=perf -count=1 -args -image-tag=$TAG -image-registry=$REGISTRY -image-namespace=$NAMESPACE -retina-mode=$MODE + + - name: Cleanup resource group + if: always() + shell: bash + run: | + if az group exists --name "$CLUSTER_NAME" 2>/dev/null | grep -q true; then + echo "Deleting resource group $CLUSTER_NAME..." + az group delete --name "$CLUSTER_NAME" --yes --no-wait || true + fi From f5239ffabc26815c467109877b10403ac3ecb03b Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 13 Apr 2026 13:48:32 -0400 Subject: [PATCH 308/448] feat(tcpretrans): rewrite plugin with native cilium/ebpf (#2152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description **PR 1 of 2** for removing inspektor-gadget from retina plugins (split from #2148 per review feedback) Cilium v1.19.2 pins `cilium/ebpf` at a version that removed `CollectionSpec.RewriteConstants()`, which inspektor-gadget relies on. Upgrading IG is not viable — v0.42.0+ removed the built-in `trace/tcpretrans` gadget entirely. This PR replaces the IG-based implementation with a native cilium/ebpf one ahead of the Cilium upgrade. - **BPF program**: New `tracepoint/tcp/tcp_retransmit_skb` program (kernel 5.8+ for `bpf_ktime_get_boot_ns`) with `BPF_CORE_READ` for CO-RE field relocation. Handles the kernel 6.17 tracepoint struct rename via CO-RE type flavors. TCP flags read from `tcp_skb_cb`. Supports IPv4 and IPv6. - **Go plugin**: Perf buffer event loop with worker goroutines, replacing the IG tracer/gadget-context pattern. `SetupChannel` now wires up the external channel (was a no-op under IG), enabling the advanced metrics module to receive events directly. - **Build**: Pre-compiled via `bpf2go@v0.18.0` with per-arch targets (amd64 + arm64) and embedded in the binary — no runtime compilation. `Compile()` and `Generate()` retained as no-ops for plugin manager lifecycle compatibility. - **`ToFlow` IPv6 labeling** (`pkg/utils/flow_utils.go`): now derives `IpVersion` from `sourceIP.To4()` instead of hardcoding `IPVersion_IPv4`, so IPv6 retransmission flows are labeled correctly. Backward-compatible for every existing IPv4 caller. - **No dependency changes**: Works with existing `cilium/ebpf` v0.18.0 in `go.mod`. ## Related Issue Partial fix for #1788 Split from #2148 Related: #2162 (chart fix surfaced while validating this PR — latent helm-upgrade reload bug for the operator ConfigMap) ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Testing Completed ### Standard / Advanced mode (AKS cluster `retinaTest-v119`, 3-node, k8s v1.33.6, kernel 5.15.0-1102-azure) Image: `acnpublic.azurecr.io/microsoft/retina/retina-agent:f4adc1e0-fix1-linux-amd64` Plugin initialized and attached on all three agent pods: ``` level=info caller=common/common_linux.go:79 msg="perf reader created" Map=PerfEventArray(retina_tcpretrans_events)#100 PageSize=4096 BufferSize=65536 level=info caller=tcpretrans/tcpretrans_linux.go:106 msg="tcpretrans plugin initialized" level=info caller=pluginmanager/pluginmanager.go:174 msg="starting plugin tcpretrans" ``` `BufferSize=65536` = 4096 × 16 pages, confirming the starting buffer size is live (down from an initial oversized default). Advanced metric flowing with real pod-level labels, counter incrementing in real time: ``` networkobservability_adv_tcpretrans_count{direction="egress",ip="10.224.1.183",namespace="kube-system",podname="konnectivity-agent-5858c6b5d7-882m2"} 6 → 7 → 9 networkobservability_adv_tcpretrans_count{direction="egress",ip="10.224.2.41",namespace="kube-system",podname="metrics-server-b957f9d87-tg22p"} 1 ``` Cross-checked against the node-level TCP stats from linuxutil on the same pod: `networkobservability_tcp_connection_stats{statistic_name="TCPLostRetransmit"} = 55` — different data source (kernel TCP stats vs kernel tracepoint), same order of magnitude. ### Advanced mode with remote context (source + destination labels) With `remoteContext=true` and `destinationLabels` set on the `tcp_retransmission_count` entry in the `MetricsConfiguration` CRD: ``` networkobservability_adv_tcpretrans_count{ source_ip="10.224.1.183",source_namespace="kube-system",source_podname="konnectivity-agent-5858c6b5d7-882m2", destination_ip="51.143.116.92",destination_namespace="kubernetes-apiserver",destination_podname="kubernetes-apiserver", direction="EGRESS" } 4 ``` No plugin changes were needed for remote context — the rewrite already populates both sides of the flow through `utils.ToFlow`, the enricher handles both sides, and the metrics module is already wired to emit both label sets when configured. Discovering this path is what led to filing #2162. ### Build / vet / test ```bash go build ./... # clean go vet ./pkg/utils/... ./pkg/plugin/tcpretrans/... # clean gofumpt -l pkg/utils/flow_utils.go pkg/plugin/tcpretrans/ # clean go test -tags=unit,dashboard ./pkg/plugin/... ./pkg/module/... # all pass ``` All existing `utils.ToFlow` callers (dropreason, dns, packetparser, latency_test.go) still pass — the `IpVersion` derivation is backward-compatible for every IPv4 caller. ## Additional Notes - PR 2 of 2 (#2153, `plugin/dns-ebpf`) rewrites the DNS plugin with the same approach. - After both merge, inspektor-gadget can be fully removed in the Cilium v1.19 upgrade PR. Signed-off-by: Quang Nguyen --- docs/03-Metrics/plugins/Linux/tcpretrans.md | 4 +- pkg/plugin/tcpretrans/_cprog/tcpretrans.c | 192 ++++++++++ .../tcpretrans/tcpretrans_arm64_bpfel.go | 149 ++++++++ .../tcpretrans/tcpretrans_arm64_bpfel.o | 0 pkg/plugin/tcpretrans/tcpretrans_ebpf_test.go | 91 +++++ pkg/plugin/tcpretrans/tcpretrans_linux.go | 306 +++++++++++----- .../tcpretrans/tcpretrans_linux_test.go | 328 ++++++++++++++++++ pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.go | 149 ++++++++ pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.o | 0 pkg/plugin/tcpretrans/types_linux.go | 22 +- pkg/utils/flow_utils.go | 11 +- 11 files changed, 1144 insertions(+), 108 deletions(-) create mode 100644 pkg/plugin/tcpretrans/_cprog/tcpretrans.c create mode 100644 pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.go create mode 100644 pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.o create mode 100644 pkg/plugin/tcpretrans/tcpretrans_ebpf_test.go create mode 100644 pkg/plugin/tcpretrans/tcpretrans_linux_test.go create mode 100644 pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.go create mode 100644 pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.o diff --git a/docs/03-Metrics/plugins/Linux/tcpretrans.md b/docs/03-Metrics/plugins/Linux/tcpretrans.md index 9b962dea4c..81270750f3 100644 --- a/docs/03-Metrics/plugins/Linux/tcpretrans.md +++ b/docs/03-Metrics/plugins/Linux/tcpretrans.md @@ -8,13 +8,15 @@ The `tcpretrans` plugin requires the `CAP_SYS_ADMIN` capability. ## Architecture -The plugin utilizes eBPF to gather data. +The plugin uses a native eBPF tracepoint (`tracepoint/tcp/tcp_retransmit_skb`) to capture TCP retransmission events. The BPF program extracts source/destination IPs, ports, and TCP flags, then streams events to user space via a perf buffer. + The plugin does not generate Basic metrics. In Advanced mode (see [Metric Modes](../../modes/modes.md)), the plugin turns an eBPF result into an enriched `Flow` (adding Pod information based on IP), then sends the `Flow` to an external channel so that a tcpretrans module can create Pod-Level metrics. ### Code locations - Plugin and eBPF code: *pkg/plugin/tcpretrans/* +- BPF C source: *pkg/plugin/tcpretrans/_cprog/tcpretrans.c* - Module for extra Advanced metrics: *pkg/module/metrics/tcpretrans.go* ## Metrics diff --git a/pkg/plugin/tcpretrans/_cprog/tcpretrans.c b/pkg/plugin/tcpretrans/_cprog/tcpretrans.c new file mode 100644 index 0000000000..e6f1ee7c02 --- /dev/null +++ b/pkg/plugin/tcpretrans/_cprog/tcpretrans.c @@ -0,0 +1,192 @@ +//go:build ignore + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// tcpretrans — eBPF tracepoint program for TCP retransmission tracking. +// +// Attaches to the kernel tracepoint "tcp/tcp_retransmit_skb" which fires +// every time the kernel retransmits a TCP segment. For each event we +// extract the 5-tuple (src/dst IP + port, protocol), TCP state, and the +// TCP flags byte, then push the result to userspace via a perf buffer. +// +// Key design decisions: +// +// Kernel version portability (CO-RE) +// This program is compiled once and must load on any kernel from 5.8+. +// (5.8 is the minimum because we use bpf_ktime_get_boot_ns, added in +// commit 71d19214776e; the tracepoint itself exists since 4.15.) +// The kernel can change struct layouts between versions, so we never +// hard-code field offsets. Instead every field read goes through +// BPF_CORE_READ / bpf_core_field_offset, which the loader (cilium/ebpf) +// patches at load time to match the running kernel's actual layout. +// +// Tracepoint struct rename (kernel 6.17) +// Older kernels expose the tracepoint context as +// "struct trace_event_raw_tcp_event_sk_skb" (shared with tcp_send_reset). +// Kernel 6.17 (commit ad892e912b84) converted tcp_retransmit_skb to its +// own TRACE_EVENT with a dedicated struct and an added "err" field. +// We define both names using libbpf's ___flavor suffix convention — the +// loader strips the suffix and matches whichever name exists in the +// running kernel's BTF. +// See: https://nakryiko.com/posts/bpf-core-reference-guide/#handling-incompatible-field-and-type-changes +// bpf_core_type_exists() picks the right branch; the verifier removes +// the dead one. +// +// Reading IPs from the sock, not the tracepoint context +// The tracepoint context has pre-copied IP fields (saddr/daddr), but +// reading them would require type-branching for both struct names. +// Instead we read IPs from the sock struct (sk->__sk_common.*), which +// has the same data and a stable layout across all kernel versions. +// +// Ref: https://github.com/inspektor-gadget/inspektor-gadget/blob/c414fc1/gadgets/trace_tcpretrans/program.bpf.c + +#include "vmlinux.h" +#include "bpf_helpers.h" +#include "bpf_core_read.h" + +char __license[] SEC("license") = "Dual MIT/GPL"; + +// Tracepoint context structs — two flavors for kernel version portability. +// +// The ___old / ___new suffixes are "CO-RE flavors": the loader strips +// everything after ___ when searching the kernel's BTF for a matching +// type. This avoids collisions with vmlinux.h (which may define either +// name depending on the kernel it was generated from). + +// Kernel < 6.17: shared struct for tcp_retransmit_skb and tcp_send_reset. +struct trace_event_raw_tcp_event_sk_skb___old { + struct trace_entry ent; + const void *skbaddr; // pointer to the retransmitted sk_buff + const void *skaddr; // pointer to the sock (TCP connection) + int state; // TCP state (ESTABLISHED, SYN_SENT, …) + __u16 sport; // source port + __u16 dport; // destination port + __u16 family; // address family (AF_INET / AF_INET6) + __u8 saddr[4]; // source IPv4 (pre-copied from sock) + __u8 daddr[4]; // dest IPv4 + __u8 saddr_v6[16]; // source IPv6 + __u8 daddr_v6[16]; // dest IPv6 + char __data[0]; +}; + +// Kernel >= 6.17: per-tracepoint struct, adds an 'err' field. +struct trace_event_raw_tcp_retransmit_skb___new { + struct trace_entry ent; + const void *skbaddr; + const void *skaddr; + int state; + __u16 sport; + __u16 dport; + __u16 family; + __u8 saddr[4]; + __u8 daddr[4]; + __u8 saddr_v6[16]; + __u8 daddr_v6[16]; + int err; // retransmission error code (new in 6.17) + char __data[0]; +}; + +struct tcpretrans_event { + __u64 timestamp; // boot time in nanoseconds (includes suspend) + __u32 src_ip; // source IPv4 (network byte order) + __u32 dst_ip; // destination IPv4 (network byte order) + __u32 state; // TCP state enum + __u16 src_port; // source port (host byte order) + __u16 dst_port; // destination port (host byte order) + __u8 src_ip6[16]; // source IPv6 address + __u8 dst_ip6[16]; // destination IPv6 address + __u8 tcpflags; // TCP flags byte (FIN/SYN/RST/PSH/ACK/URG/ECE/CWR) + __u8 af; // address family shorthand (4 = IPv4, 6 = IPv6) +}; + +// Needed by bpf2go's -type flag to generate the Go struct. +const struct tcpretrans_event *unused_tcpretrans_event __attribute__((unused)); + +// Perf buffer map — one ring per CPU, sized by the Go loader. +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u32)); +} retina_tcpretrans_events SEC(".maps"); + +// Helper macro — reads the five tracepoint fields we need regardless of +// which struct flavor is active. The unused branch is eliminated by the +// verifier at load time. +#define READ_TP_FIELDS(tp_type, ctx, out_state, out_sport, out_dport, \ + out_sk, out_skb) \ +do { \ + tp_type *tp = (tp_type *)(ctx); \ + (out_state) = BPF_CORE_READ(tp, state); \ + (out_sport) = BPF_CORE_READ(tp, sport); \ + (out_dport) = BPF_CORE_READ(tp, dport); \ + (out_sk) = (const struct sock *)BPF_CORE_READ(tp, skaddr); \ + (out_skb) = (const void *)BPF_CORE_READ(tp, skbaddr); \ +} while (0) + +SEC("tracepoint/tcp/tcp_retransmit_skb") +int retina_tcp_retransmit_skb(void *ctx) { + struct tcpretrans_event event = {}; + + event.timestamp = bpf_ktime_get_boot_ns(); + + const struct sock *sk; + const void *skbaddr; + + // Detect which tracepoint struct the running kernel uses. + if (bpf_core_type_exists(struct trace_event_raw_tcp_retransmit_skb___new)) { + READ_TP_FIELDS(struct trace_event_raw_tcp_retransmit_skb___new, + ctx, event.state, event.src_port, + event.dst_port, sk, skbaddr); + } else { + READ_TP_FIELDS(struct trace_event_raw_tcp_event_sk_skb___old, + ctx, event.state, event.src_port, + event.dst_port, sk, skbaddr); + } + + // Read address family and IPs from the sock. These fields live in + // sock_common (embedded in every sock) and are stable across versions. + __u16 family = 0; + BPF_CORE_READ_INTO(&family, sk, __sk_common.skc_family); + + if (family == 2) { // AF_INET + event.af = 4; + BPF_CORE_READ_INTO(&event.src_ip, sk, + __sk_common.skc_rcv_saddr); + BPF_CORE_READ_INTO(&event.dst_ip, sk, __sk_common.skc_daddr); + } else if (family == 10) { // AF_INET6 + event.af = 6; + BPF_CORE_READ_INTO(event.src_ip6, sk, + __sk_common.skc_v6_rcv_saddr.in6_u.u6_addr8); + BPF_CORE_READ_INTO(event.dst_ip6, sk, + __sk_common.skc_v6_daddr.in6_u.u6_addr8); + } else { + return 0; + } + + // Read TCP flags from the skb's control buffer. + // + // Every sk_buff has a 48-byte scratch area called "cb" (char[48]). + // For TCP, the kernel casts this area to "struct tcp_skb_cb" via the + // TCP_SKB_CB() macro: + // #define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0])) + // See: https://github.com/torvalds/linux/blob/v6.12/include/net/tcp.h#L989 + // + // We mirror that cast here. Neither &skb->cb[0] nor &tcb->tcp_flags + // dereferences memory — they only compute addresses, with the compiler + // recording CO-RE relocations for both field offsets. The single + // bpf_probe_read_kernel() does the actual read. This is the same + // pattern used by inspektor-gadget's trace_tcpretrans: + // https://github.com/inspektor-gadget/inspektor-gadget/blob/c414fc1/gadgets/trace_tcpretrans/program.bpf.c#L158-L163 + if (skbaddr) { + struct sk_buff *skb = (struct sk_buff *)skbaddr; + struct tcp_skb_cb *tcb = (struct tcp_skb_cb *)&(skb->cb[0]); + bpf_probe_read_kernel(&event.tcpflags, sizeof(event.tcpflags), + &tcb->tcp_flags); + } + + bpf_perf_event_output(ctx, &retina_tcpretrans_events, BPF_F_CURRENT_CPU, + &event, sizeof(event)); + + return 0; +} diff --git a/pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.go b/pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.go new file mode 100644 index 0000000000..5b2826563c --- /dev/null +++ b/pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.go @@ -0,0 +1,149 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 + +package tcpretrans + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type tcpretransTcpretransEvent struct { + Timestamp uint64 + SrcIp uint32 + DstIp uint32 + State uint32 + SrcPort uint16 + DstPort uint16 + SrcIp6 [16]uint8 + DstIp6 [16]uint8 + Tcpflags uint8 + Af uint8 + _ [6]byte +} + +// loadTcpretrans returns the embedded CollectionSpec for tcpretrans. +func loadTcpretrans() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_TcpretransBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load tcpretrans: %w", err) + } + + return spec, err +} + +// loadTcpretransObjects loads tcpretrans and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *tcpretransObjects +// *tcpretransPrograms +// *tcpretransMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadTcpretransObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadTcpretrans() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// tcpretransSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransSpecs struct { + tcpretransProgramSpecs + tcpretransMapSpecs + tcpretransVariableSpecs +} + +// tcpretransProgramSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransProgramSpecs struct { + RetinaTcpRetransmitSkb *ebpf.ProgramSpec `ebpf:"retina_tcp_retransmit_skb"` +} + +// tcpretransMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransMapSpecs struct { + RetinaTcpretransEvents *ebpf.MapSpec `ebpf:"retina_tcpretrans_events"` +} + +// tcpretransVariableSpecs contains global variables before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransVariableSpecs struct { + UnusedTcpretransEvent *ebpf.VariableSpec `ebpf:"unused_tcpretrans_event"` +} + +// tcpretransObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransObjects struct { + tcpretransPrograms + tcpretransMaps + tcpretransVariables +} + +func (o *tcpretransObjects) Close() error { + return _TcpretransClose( + &o.tcpretransPrograms, + &o.tcpretransMaps, + ) +} + +// tcpretransMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransMaps struct { + RetinaTcpretransEvents *ebpf.Map `ebpf:"retina_tcpretrans_events"` +} + +func (m *tcpretransMaps) Close() error { + return _TcpretransClose( + m.RetinaTcpretransEvents, + ) +} + +// tcpretransVariables contains all global variables after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransVariables struct { + UnusedTcpretransEvent *ebpf.Variable `ebpf:"unused_tcpretrans_event"` +} + +// tcpretransPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransPrograms struct { + RetinaTcpRetransmitSkb *ebpf.Program `ebpf:"retina_tcp_retransmit_skb"` +} + +func (p *tcpretransPrograms) Close() error { + return _TcpretransClose( + p.RetinaTcpRetransmitSkb, + ) +} + +func _TcpretransClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed tcpretrans_arm64_bpfel.o +var _TcpretransBytes []byte diff --git a/pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.o b/pkg/plugin/tcpretrans/tcpretrans_arm64_bpfel.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pkg/plugin/tcpretrans/tcpretrans_ebpf_test.go b/pkg/plugin/tcpretrans/tcpretrans_ebpf_test.go new file mode 100644 index 0000000000..0f8a43c587 --- /dev/null +++ b/pkg/plugin/tcpretrans/tcpretrans_ebpf_test.go @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build ebpf && linux + +// Tests for the tcpretrans BPF tracepoint program. +// +// These load the compiled BPF program, verify it passes the kernel verifier, +// and confirm it can attach to the tcp/tcp_retransmit_skb tracepoint. +// +// Unlike socket-filter or TC programs, tracepoint programs cannot be exercised +// with synthetic packets via BPF_PROG_TEST_RUN because the handler dereferences +// kernel pointers (skaddr, skbaddr) that cannot be mocked from userspace. +// The load+attach tests still provide significant value: they catch verifier +// regressions, CO-RE relocation failures, and missing tracepoints. +// +// Requires: root (or CAP_BPF+CAP_SYS_ADMIN), Linux kernel 5.8+ +// (bpf_ktime_get_boot_ns helper, commit 71d19214776e). +// Run: sudo go test -tags=ebpf -v -count=1 ./pkg/plugin/tcpretrans/... + +package tcpretrans + +import ( + "os" + "testing" + + "github.com/cilium/ebpf/link" + "github.com/cilium/ebpf/perf" + kcfg "github.com/microsoft/retina/pkg/config" + "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/plugin/ebpftest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func loadTestObjects(t *testing.T) *tcpretransObjects { + t.Helper() + ebpftest.RequirePrivileged(t) + + spec, err := loadTcpretrans() + require.NoError(t, err) + ebpftest.RemoveMapPinning(spec) + + var objs tcpretransObjects + err = spec.LoadAndAssign(&objs, nil) + require.NoError(t, err) + t.Cleanup(func() { objs.Close() }) + return &objs +} + +// TestBPFLoadAndVerify verifies the compiled BPF program passes the kernel +// verifier and all expected objects (program + perf event array) are created. +func TestBPFLoadAndVerify(t *testing.T) { + objs := loadTestObjects(t) + + assert.NotNil(t, objs.RetinaTcpRetransmitSkb, "tracepoint program should be loaded") + assert.NotNil(t, objs.RetinaTcpretransEvents, "perf event array map should be created") +} + +// TestBPFTracepointAttach verifies the program can attach to the +// tcp/tcp_retransmit_skb tracepoint (stable since kernel 4.15, commit e086101b150a). +func TestBPFTracepointAttach(t *testing.T) { + objs := loadTestObjects(t) + + tp, err := link.Tracepoint("tcp", "tcp_retransmit_skb", objs.RetinaTcpRetransmitSkb, nil) + require.NoError(t, err, "should attach to tcp/tcp_retransmit_skb tracepoint") + t.Cleanup(func() { tp.Close() }) +} + +// TestBPFPerfReaderCreate verifies a perf reader can be opened on the events map. +func TestBPFPerfReaderCreate(t *testing.T) { + objs := loadTestObjects(t) + + reader, err := perf.NewReader(objs.RetinaTcpretransEvents, os.Getpagesize()*4) + require.NoError(t, err, "should create perf reader") + t.Cleanup(func() { reader.Close() }) +} + +// TestBPFStopAfterInitWithoutStart exercises the fixed resource-leak path: +// Init() loads BPF objects and attaches the tracepoint, but Start() is never +// called. Stop() must still release all kernel resources. +func TestBPFStopAfterInitWithoutStart(t *testing.T) { + ebpftest.RequirePrivileged(t) + + log.SetupZapLogger(log.GetDefaultLogOpts()) + + p := New(&kcfg.Config{EnablePodLevel: true}) + require.NoError(t, p.Init()) + // Start() deliberately not called. + require.NoError(t, p.Stop(), "Stop() must clean up even without Start()") +} diff --git a/pkg/plugin/tcpretrans/tcpretrans_linux.go b/pkg/plugin/tcpretrans/tcpretrans_linux.go index 1f4b994f4e..21d1681518 100644 --- a/pkg/plugin/tcpretrans/tcpretrans_linux.go +++ b/pkg/plugin/tcpretrans/tcpretrans_linux.go @@ -1,30 +1,46 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -// Package tcpretrans contains the Retina tcpretrans plugin. It utilizes inspektor-gadget to trace TCP retransmissions. +// Package tcpretrans contains the Retina tcpretrans plugin. It utilizes eBPF to trace TCP retransmissions. package tcpretrans import ( "context" + "errors" "fmt" "net" - "strings" + "unsafe" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" - gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context" - "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcpretrans/tracer" - "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcpretrans/types" - "github.com/inspektor-gadget/inspektor-gadget/pkg/socketenricher" - "github.com/inspektor-gadget/inspektor-gadget/pkg/utils/host" + "github.com/cilium/ebpf/link" + "github.com/cilium/ebpf/perf" + "github.com/microsoft/retina/internal/ktime" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/enricher" "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/metrics" + plugincommon "github.com/microsoft/retina/pkg/plugin/common" "github.com/microsoft/retina/pkg/plugin/registry" "github.com/microsoft/retina/pkg/utils" "go.uber.org/zap" "golang.org/x/sys/unix" ) +// Per-arch target needed because vmlinux.h differs between amd64/arm64. +// Cross-generate: GOARCH=arm64 go generate ./pkg/plugin/tcpretrans/... +// +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go@v0.18.0 -cflags "-Wall" -target ${GOARCH} -type tcpretrans_event tcpretrans ./_cprog/tcpretrans.c -- -I../lib/_${GOARCH} -I../lib/common/libbpf/_src + +const ( + // perCPUBuffer is the starting perf buffer size in pages per CPU. + // NewPerfReader halves this on ENOMEM down to 1 page. Retransmits are + // comparatively rare (much less frequent than packet drops), so 16 pages + // (64 KiB per CPU) is plenty — same starting point as dropreason. + perCPUBuffer = 16 + recordsBuffer = 500 // Channel buffer for records + workers = 2 // Number of worker goroutines +) + func init() { registry.Add(name, New) } @@ -40,33 +56,55 @@ func (t *tcpretrans) Name() string { return name } -func (t *tcpretrans) Generate(ctx context.Context) error { - return nil -} - -func (t *tcpretrans) Compile(ctx context.Context) error { - return nil -} +// Generate and Compile are no-ops. The plugin manager lifecycle requires them, +// but tcpretrans uses bpf2go which pre-compiles the BPF program at build time +// and embeds it in the binary — no runtime code generation or compilation needed. +func (t *tcpretrans) Generate(_ context.Context) error { return nil } +func (t *tcpretrans) Compile(_ context.Context) error { return nil } func (t *tcpretrans) Init() error { if !t.cfg.EnablePodLevel { t.l.Warn("tcpretrans will not init because pod level is disabled") return nil } - // Create tracer. In this case no parameters are passed. - if err := host.Init(host.Config{}); err != nil { - t.l.Error("failed to init host", zap.Error(err)) - return fmt.Errorf("failed to init host: %w", err) + + // tcpretrans has a single per-CPU perf event array and no shared maps, + // so there's nothing to pin — leaving CollectionOptions nil avoids + // dropping a dangling entry under /sys/fs/bpf. + objs := &tcpretransObjects{} + if err := loadTcpretransObjects(objs, nil); err != nil { + return fmt.Errorf("failed to load eBPF objects: %w", err) + } + // Clean up loaded objects if a later step fails. + ok := false + defer func() { + if !ok { + objs.Close() + } + }() + + // Attach to the tcp/tcp_retransmit_skb tracepoint (stable API, kernel 4.15+) + tp, err := link.Tracepoint("tcp", "tcp_retransmit_skb", objs.RetinaTcpRetransmitSkb, nil) + if err != nil { + return fmt.Errorf("failed to attach tracepoint tcp/tcp_retransmit_skb: %w", err) } - t.tracer = &tracer.Tracer{} - t.tracer.SetEventHandler(t.eventHandler) - socketEnricher, err := socketenricher.NewSocketEnricher() + defer func() { + if !ok { + tp.Close() + } + }() + + reader, err := plugincommon.NewPerfReader(t.l, objs.RetinaTcpretransEvents, perCPUBuffer, 1) if err != nil { - t.l.Error("failed to new socketEnricher", zap.Error(err)) - return fmt.Errorf("failed to new socketEnricher: %w", err) + return fmt.Errorf("failed to create perf reader: %w", err) } - t.tracer.SetSocketEnricherMap(socketEnricher.SocketsMap()) - t.l.Info("Initialized tcpretrans plugin") + + t.objs = objs + t.hooks = append(t.hooks, tp) + t.reader = reader + ok = true + + t.l.Info("tcpretrans plugin initialized") return nil } @@ -75,108 +113,188 @@ func (t *tcpretrans) Start(ctx context.Context) error { t.l.Warn("tcpretrans will not start because pod level is disabled") return nil } - // Set up enricher + if enricher.IsInitialized() { t.enricher = enricher.Instance() } else { - t.l.Error(errEnricherNotInitialized.Error()) - return errEnricherNotInitialized + t.l.Warn("retina enricher is not initialized") } - t.gadgetCtx = gadgetcontext.New(ctx, "tcpretrans", nil, nil, nil, nil, nil, nil, nil, nil, 0, nil) - err := t.tracer.Run(t.gadgetCtx) - if err != nil { - t.l.Error("Failed to run tracer", zap.Error(err)) - return err - } - t.l.Info("Started tcpretrans plugin") - return nil + t.recordsChannel = make(chan perf.Record, recordsBuffer) + + return t.run(ctx) } -func (t *tcpretrans) Stop() error { - if !t.cfg.EnablePodLevel { - return nil +func (t *tcpretrans) run(ctx context.Context) error { + for range workers { + t.wg.Add(1) + go t.processRecord(ctx) } - if t.gadgetCtx == nil { - t.l.Warn("tcpretrans plugin does not have a gadget context") - return nil + // readEvents is deliberately not tracked in wg: its reader.Read() call + // blocks until the perf reader is closed, which we do immediately below + // on ctx cancellation to unblock it. + go t.readEvents(ctx) + + <-ctx.Done() + // Close the reader before waiting on workers so readEvents unblocks + // from its pending Read() instead of racing to send records onto a + // channel that no worker is draining anymore. Safe to call Close twice + // — Stop() will no-op if the reader has already been closed. + if t.reader != nil { + if err := t.reader.Close(); err != nil { + t.l.Warn("failed to close perf reader", zap.Error(err)) + } } - t.gadgetCtx.Cancel() - t.l.Info("Stopped tcpretrans plugin") + t.wg.Wait() return nil } -func (t *tcpretrans) SetupChannel(ch chan *v1.Event) error { - t.l.Warn("SetupChannel is not supported by plugin", zap.String("plugin", name)) - return nil +func (t *tcpretrans) readEvents(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + default: + record, err := t.reader.Read() + if err != nil { + if errors.Is(err, perf.ErrClosed) { + return + } + t.l.Error("Error reading perf event", zap.Error(err)) + continue + } + + if record.LostSamples > 0 { + metrics.LostEventsCounter.WithLabelValues(utils.Kernel, name).Add(float64(record.LostSamples)) + continue + } + + select { + case t.recordsChannel <- record: + default: + metrics.LostEventsCounter.WithLabelValues(utils.BufferedChannel, name).Inc() + } + } + } +} + +func (t *tcpretrans) processRecord(ctx context.Context) { + defer t.wg.Done() + + for { + select { + case <-ctx.Done(): + return + case record := <-t.recordsChannel: + t.handleTCPRetransEvent(record) + } + } } -func (t *tcpretrans) eventHandler(event *types.Event) { - if event == nil { +func (t *tcpretrans) handleTCPRetransEvent(record perf.Record) { + eventSize := int(unsafe.Sizeof(tcpretransTcpretransEvent{})) + if len(record.RawSample) < eventSize { return } - if event.IPVersion != 4 { + event := (*tcpretransTcpretransEvent)(unsafe.Pointer(&record.RawSample[0])) //nolint:gosec // perf record is aligned + + var srcIP, dstIP net.IP + switch event.Af { + case 4: // IPv4 + var srcBuf, dstBuf [net.IPv4len]byte + *(*uint32)(unsafe.Pointer(&srcBuf[0])) = event.SrcIp //nolint:gosec // same size + *(*uint32)(unsafe.Pointer(&dstBuf[0])) = event.DstIp //nolint:gosec // same size + srcIP = srcBuf[:] + dstIP = dstBuf[:] + case 6: // IPv6 + srcIP = event.SrcIp6[:] + dstIP = event.DstIp6[:] + default: return } - // TODO add metric here or add a enriched value fl := utils.ToFlow( t.l, - int64(event.Timestamp), - net.ParseIP(event.SrcEndpoint.L3Endpoint.Addr).To4(), // Precautionary To4() call. - net.ParseIP(event.DstEndpoint.L3Endpoint.Addr).To4(), // Precautionary To4() call. - uint32(event.SrcEndpoint.Port), - uint32(event.DstEndpoint.Port), - unix.IPPROTO_TCP, // only TCP can have retransmissions - 0, // drop reason packet doesn't have a direction yet, so we set it to 0 + ktime.MonotonicOffset.Nanoseconds()+int64(event.Timestamp), //nolint:gosec // timestamp fits in int64 + srcIP, dstIP, + uint32(event.SrcPort), uint32(event.DstPort), + unix.IPPROTO_TCP, 0, utils.Verdict_RETRANSMISSION, ) - if fl == nil { - t.l.Warn("Could not convert tracer Event to flow", zap.Any("tracer event", event)) return } - syn, ack, fin, rst, psh, urg, ece, cwr, ns := getTCPFlags(event.Tcpflags) - utils.AddTCPFlags(fl, syn, ack, fin, rst, psh, urg, ece, cwr, ns) - // This is only for development purposes. - // Removing this makes logs way too chatter-y. - // dr.l.Debug("DropReason Packet Received", zap.Any("flow", fl), zap.Any("Raw Bpf Event", bpfEvent), zap.Uint32("drop type", bpfEvent.Key.DropType)) + syn := flagBit(event.Tcpflags, 0x02) + ack := flagBit(event.Tcpflags, 0x10) + fin := flagBit(event.Tcpflags, 0x01) + rst := flagBit(event.Tcpflags, 0x04) + psh := flagBit(event.Tcpflags, 0x08) + urg := flagBit(event.Tcpflags, 0x20) + ece := flagBit(event.Tcpflags, 0x40) + cwr := flagBit(event.Tcpflags, 0x80) + // NS is always 0: tcp_skb_cb->tcp_flags is a single byte that only holds + // byte 13 of the TCP header (FIN/SYN/RST/PSH/ACK/URG/ECE/CWR). NS lives + // in byte 12 and isn't carried in the control block. It's also effectively + // deprecated — RFC 8311 reclassified ECN nonce as historic — so preserving + // it would require parsing the full TCP header from the skb clone for no + // observable benefit. + utils.AddTCPFlags(fl, syn, ack, fin, rst, psh, urg, ece, cwr, 0) - // Write the event to the enricher. - t.enricher.Write(&v1.Event{ + ev := &v1.Event{ Event: fl, Timestamp: fl.Time, - }) + } + + if t.enricher != nil { + t.enricher.Write(ev) + } + + if t.externalChannel != nil { + select { + case t.externalChannel <- ev: + default: + metrics.LostEventsCounter.WithLabelValues(utils.ExternalChannel, name).Inc() + } + } } -//nolint:gocritic // This should be rewritten to return a struct. -func getTCPFlags(flags string) (syn, ack, fin, rst, psh, urg, ece, cwr, ns uint16) { - // this limiter is used in IG to put all the flags together - syn, ack, fin, rst, psh, urg = 0, 0, 0, 0, 0, 0 - result := strings.Split(flags, "|") - for _, flag := range result { - switch flag { - case "SYN": - syn = 1 - case "ACK": - ack = 1 - case "FIN": - fin = 1 - case "RST": - rst = 1 - case "PSH": - psh = 1 - case "URG": - urg = 1 - case "ECE": - ece = 1 - case "CWR": - cwr = 1 - case "NS": - ns = 1 +func (t *tcpretrans) Stop() error { + if !t.cfg.EnablePodLevel { + return nil + } + // Always clean up kernel resources regardless of whether Start() was + // called. Init() loads BPF objects, attaches the tracepoint, and + // creates a perf reader — all of which must be released. + if t.reader != nil { + // Idempotent: run() already closes the reader on normal shutdown, + // in which case cilium/ebpf returns nil here. + if err := t.reader.Close(); err != nil { + t.l.Warn("failed to close perf reader", zap.Error(err)) + } + } + for _, h := range t.hooks { + if err := h.Close(); err != nil { + t.l.Warn("failed to close hook", zap.Error(err)) + } + } + if t.objs != nil { + if err := t.objs.Close(); err != nil { + t.l.Warn("failed to close eBPF objects", zap.Error(err)) } } - return + return nil +} + +func (t *tcpretrans) SetupChannel(ch chan *v1.Event) error { + t.externalChannel = ch + return nil +} + +func flagBit(flags, bit uint8) uint16 { + if flags&bit != 0 { + return 1 + } + return 0 } diff --git a/pkg/plugin/tcpretrans/tcpretrans_linux_test.go b/pkg/plugin/tcpretrans/tcpretrans_linux_test.go new file mode 100644 index 0000000000..f6cca3891c --- /dev/null +++ b/pkg/plugin/tcpretrans/tcpretrans_linux_test.go @@ -0,0 +1,328 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package tcpretrans + +import ( + "net" + "os" + "testing" + "unsafe" + + v1 "github.com/cilium/cilium/pkg/hubble/api/v1" + "github.com/cilium/ebpf/perf" + kcfg "github.com/microsoft/retina/pkg/config" + "github.com/microsoft/retina/pkg/enricher" + "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/metrics" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" +) + +func TestMain(m *testing.M) { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + metrics.InitializeMetrics() + os.Exit(m.Run()) +} + +// --- helpers --- + +// buildTestRecord serialises a tcpretransTcpretransEvent into a perf.Record +// using the same memory layout the BPF perf ring produces. +func buildTestRecord(event tcpretransTcpretransEvent) perf.Record { + eventSize := int(unsafe.Sizeof(event)) + eventBytes := unsafe.Slice((*byte)(unsafe.Pointer(&event)), eventSize) //nolint:gosec // test-only + buf := make([]byte, eventSize) + copy(buf, eventBytes) + return perf.Record{RawSample: buf} +} + +// ipv4Native converts a dotted-quad string to the uint32 representation +// stored by the BPF program (network byte order bytes read as LE uint32). +func ipv4Native(s string) uint32 { + ip := net.ParseIP(s).To4() + return *(*uint32)(unsafe.Pointer(&ip[0])) //nolint:gosec // test-only +} + +// ipv6Bytes converts an IPv6 string to the [16]uint8 stored by the BPF program. +func ipv6Bytes(s string) [16]uint8 { + var b [16]uint8 + copy(b[:], net.ParseIP(s).To16()) + return b +} + +// newTestPlugin returns a minimal tcpretrans for unit testing with an +// external channel to receive emitted events. +func newTestPlugin(ch chan *v1.Event) *tcpretrans { + return &tcpretrans{ + cfg: &kcfg.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + externalChannel: ch, + } +} + +// --- constructor / lifecycle --- + +func TestNew(t *testing.T) { + cfg := &kcfg.Config{EnablePodLevel: true} + p := New(cfg) + require.NotNil(t, p) + assert.Equal(t, name, p.Name()) +} + +func TestSetupChannel(t *testing.T) { + p := &tcpretrans{ + cfg: &kcfg.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + } + ch := make(chan *v1.Event, 10) + require.NoError(t, p.SetupChannel(ch)) + assert.Equal(t, ch, p.externalChannel) +} + +func TestStop_PodLevelDisabled(t *testing.T) { + p := &tcpretrans{ + cfg: &kcfg.Config{EnablePodLevel: false}, + l: log.Logger().Named(name), + } + require.NoError(t, p.Stop()) +} + +func TestStop_NilResources(t *testing.T) { + // Stop() must not panic when Init() was never called (all resources nil). + p := &tcpretrans{ + cfg: &kcfg.Config{EnablePodLevel: true}, + l: log.Logger().Named(name), + } + require.NoError(t, p.Stop()) +} + +// --- flagBit --- + +func TestFlagBit(t *testing.T) { + tests := []struct { + name string + flags uint8 + bit uint8 + expected uint16 + }{ + {"SYN set", 0x02, 0x02, 1}, + {"SYN clear", 0x00, 0x02, 0}, + {"ACK set", 0x10, 0x10, 1}, + {"ACK clear", 0x02, 0x10, 0}, + {"FIN set", 0x01, 0x01, 1}, + {"RST set", 0x04, 0x04, 1}, + {"PSH set", 0x08, 0x08, 1}, + {"URG set", 0x20, 0x20, 1}, + {"ECE set", 0x40, 0x40, 1}, + {"CWR set", 0x80, 0x80, 1}, + {"all set", 0xFF, 0x02, 1}, + {"all set check FIN", 0xFF, 0x01, 1}, + {"none set", 0x00, 0xFF, 0}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, flagBit(tt.flags, tt.bit)) + }) + } +} + +// --- handleTCPRetransEvent --- + +func TestHandleTCPRetransEvent_IPv4(t *testing.T) { + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 1000, + SrcIp: ipv4Native("10.0.0.1"), + DstIp: ipv4Native("10.0.0.2"), + SrcPort: 12345, + DstPort: 80, + Tcpflags: 0x12, // SYN+ACK + Af: 4, + }) + + p.handleTCPRetransEvent(record) + + require.Len(t, ch, 1) + ev := <-ch + fl := ev.GetFlow() + require.NotNil(t, fl) + + assert.Equal(t, "10.0.0.1", fl.GetIP().GetSource()) + assert.Equal(t, "10.0.0.2", fl.GetIP().GetDestination()) + assert.Equal(t, uint32(12345), fl.GetL4().GetTCP().GetSourcePort()) + assert.Equal(t, uint32(80), fl.GetL4().GetTCP().GetDestinationPort()) + + flags := fl.GetL4().GetTCP().GetFlags() + require.NotNil(t, flags) + assert.True(t, flags.GetSYN(), "SYN should be set") + assert.True(t, flags.GetACK(), "ACK should be set") + assert.False(t, flags.GetFIN(), "FIN should not be set") + assert.False(t, flags.GetRST(), "RST should not be set") +} + +func TestHandleTCPRetransEvent_IPv6(t *testing.T) { + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + + srcIP := "fd00::1" + dstIP := "fd00::2" + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 2000, + SrcIp6: ipv6Bytes(srcIP), + DstIp6: ipv6Bytes(dstIP), + SrcPort: 44444, + DstPort: 443, + Tcpflags: 0x10, // ACK + Af: 6, + }) + + p.handleTCPRetransEvent(record) + + require.Len(t, ch, 1) + ev := <-ch + fl := ev.GetFlow() + require.NotNil(t, fl) + + assert.Equal(t, srcIP, fl.GetIP().GetSource()) + assert.Equal(t, dstIP, fl.GetIP().GetDestination()) + assert.Equal(t, uint32(44444), fl.GetL4().GetTCP().GetSourcePort()) + assert.Equal(t, uint32(443), fl.GetL4().GetTCP().GetDestinationPort()) +} + +func TestHandleTCPRetransEvent_AllFlags(t *testing.T) { + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 3000, + SrcIp: ipv4Native("1.2.3.4"), + DstIp: ipv4Native("5.6.7.8"), + SrcPort: 1000, + DstPort: 2000, + Tcpflags: 0xFF, + Af: 4, + }) + + p.handleTCPRetransEvent(record) + + require.Len(t, ch, 1) + flags := (<-ch).GetFlow().GetL4().GetTCP().GetFlags() + require.NotNil(t, flags) + + assert.True(t, flags.GetFIN(), "FIN") + assert.True(t, flags.GetSYN(), "SYN") + assert.True(t, flags.GetRST(), "RST") + assert.True(t, flags.GetPSH(), "PSH") + assert.True(t, flags.GetACK(), "ACK") + assert.True(t, flags.GetURG(), "URG") + assert.True(t, flags.GetECE(), "ECE") + assert.True(t, flags.GetCWR(), "CWR") + assert.False(t, flags.GetNS(), "NS is never set from tcp_skb_cb") +} + +func TestHandleTCPRetransEvent_NoFlags(t *testing.T) { + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 4000, + SrcIp: ipv4Native("1.2.3.4"), + DstIp: ipv4Native("5.6.7.8"), + SrcPort: 1000, + DstPort: 2000, + Tcpflags: 0x00, + Af: 4, + }) + + p.handleTCPRetransEvent(record) + + require.Len(t, ch, 1) + flags := (<-ch).GetFlow().GetL4().GetTCP().GetFlags() + require.NotNil(t, flags) + + assert.False(t, flags.GetFIN()) + assert.False(t, flags.GetSYN()) + assert.False(t, flags.GetRST()) + assert.False(t, flags.GetPSH()) + assert.False(t, flags.GetACK()) + assert.False(t, flags.GetURG()) + assert.False(t, flags.GetECE()) + assert.False(t, flags.GetCWR()) +} + +func TestHandleTCPRetransEvent_TruncatedRecord(t *testing.T) { + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + + // Record shorter than the event struct — must be silently dropped. + record := perf.Record{RawSample: []byte{0x01, 0x02, 0x03}} + p.handleTCPRetransEvent(record) + + assert.Empty(t, ch, "truncated record should not emit an event") +} + +func TestHandleTCPRetransEvent_UnknownAF(t *testing.T) { + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 5000, + Af: 99, // unsupported address family + }) + + p.handleTCPRetransEvent(record) + + assert.Empty(t, ch, "unknown AF should not emit an event") +} + +func TestHandleTCPRetransEvent_WithEnricher(t *testing.T) { + ctrl := gomock.NewController(t) + + menricher := enricher.NewMockEnricherInterface(ctrl) //nolint:typecheck // generated mock + menricher.EXPECT().Write(gomock.Any()).Times(1) + + ch := make(chan *v1.Event, 10) + p := newTestPlugin(ch) + p.enricher = menricher + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 6000, + SrcIp: ipv4Native("10.0.0.1"), + DstIp: ipv4Native("10.0.0.2"), + SrcPort: 5555, + DstPort: 80, + Tcpflags: 0x10, + Af: 4, + }) + + p.handleTCPRetransEvent(record) + + require.Len(t, ch, 1) +} + +func TestHandleTCPRetransEvent_ChannelFull(t *testing.T) { + // When the external channel is full, the event is dropped (not blocking). + ch := make(chan *v1.Event) // unbuffered — will always be full + p := newTestPlugin(ch) + + record := buildTestRecord(tcpretransTcpretransEvent{ + Timestamp: 7000, + SrcIp: ipv4Native("10.0.0.1"), + DstIp: ipv4Native("10.0.0.2"), + SrcPort: 1111, + DstPort: 2222, + Tcpflags: 0x02, + Af: 4, + }) + + // Must not block. + p.handleTCPRetransEvent(record) + + // Channel still empty (nobody reading), event was dropped. + assert.Empty(t, ch) +} diff --git a/pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.go b/pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.go new file mode 100644 index 0000000000..e4e9f03744 --- /dev/null +++ b/pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.go @@ -0,0 +1,149 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 + +package tcpretrans + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type tcpretransTcpretransEvent struct { + Timestamp uint64 + SrcIp uint32 + DstIp uint32 + State uint32 + SrcPort uint16 + DstPort uint16 + SrcIp6 [16]uint8 + DstIp6 [16]uint8 + Tcpflags uint8 + Af uint8 + _ [6]byte +} + +// loadTcpretrans returns the embedded CollectionSpec for tcpretrans. +func loadTcpretrans() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_TcpretransBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load tcpretrans: %w", err) + } + + return spec, err +} + +// loadTcpretransObjects loads tcpretrans and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *tcpretransObjects +// *tcpretransPrograms +// *tcpretransMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadTcpretransObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadTcpretrans() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// tcpretransSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransSpecs struct { + tcpretransProgramSpecs + tcpretransMapSpecs + tcpretransVariableSpecs +} + +// tcpretransProgramSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransProgramSpecs struct { + RetinaTcpRetransmitSkb *ebpf.ProgramSpec `ebpf:"retina_tcp_retransmit_skb"` +} + +// tcpretransMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransMapSpecs struct { + RetinaTcpretransEvents *ebpf.MapSpec `ebpf:"retina_tcpretrans_events"` +} + +// tcpretransVariableSpecs contains global variables before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type tcpretransVariableSpecs struct { + UnusedTcpretransEvent *ebpf.VariableSpec `ebpf:"unused_tcpretrans_event"` +} + +// tcpretransObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransObjects struct { + tcpretransPrograms + tcpretransMaps + tcpretransVariables +} + +func (o *tcpretransObjects) Close() error { + return _TcpretransClose( + &o.tcpretransPrograms, + &o.tcpretransMaps, + ) +} + +// tcpretransMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransMaps struct { + RetinaTcpretransEvents *ebpf.Map `ebpf:"retina_tcpretrans_events"` +} + +func (m *tcpretransMaps) Close() error { + return _TcpretransClose( + m.RetinaTcpretransEvents, + ) +} + +// tcpretransVariables contains all global variables after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransVariables struct { + UnusedTcpretransEvent *ebpf.Variable `ebpf:"unused_tcpretrans_event"` +} + +// tcpretransPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadTcpretransObjects or ebpf.CollectionSpec.LoadAndAssign. +type tcpretransPrograms struct { + RetinaTcpRetransmitSkb *ebpf.Program `ebpf:"retina_tcp_retransmit_skb"` +} + +func (p *tcpretransPrograms) Close() error { + return _TcpretransClose( + p.RetinaTcpRetransmitSkb, + ) +} + +func _TcpretransClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed tcpretrans_x86_bpfel.o +var _TcpretransBytes []byte diff --git a/pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.o b/pkg/plugin/tcpretrans/tcpretrans_x86_bpfel.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pkg/plugin/tcpretrans/types_linux.go b/pkg/plugin/tcpretrans/types_linux.go index b3856bbe3e..e48e5812ab 100644 --- a/pkg/plugin/tcpretrans/types_linux.go +++ b/pkg/plugin/tcpretrans/types_linux.go @@ -3,10 +3,10 @@ package tcpretrans import ( - "errors" + "sync" - gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context" - "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcpretrans/tracer" + v1 "github.com/cilium/cilium/pkg/hubble/api/v1" + "github.com/cilium/ebpf/perf" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/enricher" "github.com/microsoft/retina/pkg/log" @@ -15,11 +15,13 @@ import ( const name = "tcpretrans" type tcpretrans struct { - cfg *kcfg.Config - l *log.ZapLogger - tracer *tracer.Tracer - gadgetCtx *gadgetcontext.GadgetContext - enricher enricher.EnricherInterface + cfg *kcfg.Config + l *log.ZapLogger + enricher enricher.EnricherInterface + externalChannel chan *v1.Event + objs *tcpretransObjects + reader *perf.Reader + hooks []interface{ Close() error } + recordsChannel chan perf.Record + wg sync.WaitGroup } - -var errEnricherNotInitialized = errors.New("enricher not initialized") diff --git a/pkg/utils/flow_utils.go b/pkg/utils/flow_utils.go index 4a41b32d99..73a196bded 100644 --- a/pkg/utils/flow_utils.go +++ b/pkg/utils/flow_utils.go @@ -41,7 +41,8 @@ const ( // ToFlow returns a flow.Flow object. // This sets up a L3/L4 flow object. -// sourceIP, destIP are IPv4 addresses. +// sourceIP, destIP are IPv4 or IPv6 addresses; IpVersion is derived from the +// address family via net.IP.To4(). // sourcePort, destPort are TCP/UDP ports. // proto is the protocol number. Ref: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml . // observationPoint is the observation point+direction of the flow. 0 is from n/w stack to container, 1 is from container to stack, @@ -112,6 +113,11 @@ func ToFlow( verdict = flow.Verdict_FORWARDED } + ipVersion := flow.IPVersion_IPv4 + if sourceIP.To4() == nil { + ipVersion = flow.IPVersion_IPv6 + } + f := &flow.Flow{ Type: flow.FlowType_L3_L4, EventType: &flow.CiliumEventType{ @@ -121,8 +127,7 @@ func ToFlow( IP: &flow.IP{ Source: sourceIP.String(), Destination: destIP.String(), - // We only support IPv4 for now. - IpVersion: flow.IPVersion_IPv4, + IpVersion: ipVersion, }, L4: l4, TraceObservationPoint: checkpoint, From 2ce16aac6626b5385bc9601e22a577999a115371 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 14:19:46 -0400 Subject: [PATCH 309/448] deps: bump github.com/gopacket/gopacket from 1.3.1 to 1.5.0 (#2190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/gopacket/gopacket](https://github.com/gopacket/gopacket) from 1.3.1 to 1.5.0.
Release notes

Sourced from github.com/gopacket/gopacket's releases.

v1.5.0

What's Changed

New Contributors

Full Changelog: https://github.com/gopacket/gopacket/compare/v1.4.0...v1.5.0

v1.4.0

What's Changed

New Contributors

... (truncated)

Commits
  • ac0316a feat: support to parse enip and cip protocols for industrial automation (#137)
  • c656f7a fix: prevent panic when creating flows from malformed linux sll packets (#139)
  • 34a6022 afpacket: add vnet_hdr_size option that can be passed to NewTPacket (#136)
  • f251eb3 fix: Update MAC prefixes and generation logic (#138)
  • e229ad0 afpacket: add protocol option that can be passed to NewTPacket (#135)
  • f972276 gtp: assign value to data[0] after PrependBytes (#130)
  • 1365ed5 Bump actions/setup-go from 5 to 6 (#131)
  • 3df4fdc added apsp (from Google's repo) (#129)
  • cabc5c7 added ague (from google's repo) (#128)
  • fa445ca Fix Dot11InformationElement parsing panic (#124)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/gopacket/gopacket&package-manager=go_modules&previous-version=1.3.1&new-version=1.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b1121eb158..692d490e41 100644 --- a/go.mod +++ b/go.mod @@ -271,7 +271,7 @@ require ( github.com/florianl/go-tc v0.4.5 github.com/go-logr/zapr v1.3.0 github.com/google/gopacket v1.1.19 - github.com/gopacket/gopacket v1.3.1 + github.com/gopacket/gopacket v1.5.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/inspektor-gadget/inspektor-gadget v0.27.0 github.com/jellydator/ttlcache/v3 v3.4.0 diff --git a/go.sum b/go.sum index 76ee727a67..a4c9cc1927 100644 --- a/go.sum +++ b/go.sum @@ -795,8 +795,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKG github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= -github.com/gopacket/gopacket v1.3.1 h1:ZppWyLrOJNZPe5XkdjLbtuTkfQoxQ0xyMJzQCqtqaPU= -github.com/gopacket/gopacket v1.3.1/go.mod h1:3I13qcqSpB2R9fFQg866OOgzylYkZxLTmkvcXhvf6qg= +github.com/gopacket/gopacket v1.5.0 h1:9s9fcSUVKFlRV97B77Bq9XNV3ly2gvvsneFMQUGjc+M= +github.com/gopacket/gopacket v1.5.0/go.mod h1:i3NaGaqfoWKAr1+g7qxEdWsmfT+MXuWkAe9+THv8LME= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= From fc219a2983aae57f453e7c26a7de6d909b0787ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:20:03 +0000 Subject: [PATCH 310/448] deps: bump github.com/florianl/go-tc from 0.4.5 to 0.4.8 (#2192) Bumps [github.com/florianl/go-tc](https://github.com/florianl/go-tc) from 0.4.5 to 0.4.8.
Commits
  • 056c3a9 Go: update mdlayher/netlink to 1.6.2 (#303)
  • db02431 nest: use vtUnspec (#302)
  • 6deaccd Bump github/codeql-action from 4.34.1 to 4.35.1 (#301)
  • fae8828 Bump actions/setup-go from 6.3.0 to 6.4.0 (#300)
  • 8dcf505 Bump actions/download-artifact from 8.0.0 to 8.0.1 (#297)
  • 72c1017 Bump github/codeql-action from 4.32.5 to 4.34.1 (#299)
  • 51eb422 CI: bump staticcheck version (#296)
  • 21e1e1d Bump dominikh/staticcheck-action from 1.4.0 to 1.4.1 (#294)
  • 3d410b3 Bump actions/upload-artifact from 6.0.0 to 7.0.0 (#293)
  • e0c4924 Bump actions/download-artifact from 7.0.0 to 8.0.0 (#291)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/florianl/go-tc&package-manager=go_modules&previous-version=0.4.5&new-version=0.4.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 692d490e41..4879c66f0a 100644 --- a/go.mod +++ b/go.mod @@ -268,7 +268,7 @@ require ( github.com/cilium/hive v0.0.0-20250328192914-7f3c86c9c25e github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb github.com/cilium/workerpool v1.3.0 - github.com/florianl/go-tc v0.4.5 + github.com/florianl/go-tc v0.4.8 github.com/go-logr/zapr v1.3.0 github.com/google/gopacket v1.1.19 github.com/gopacket/gopacket v1.5.0 diff --git a/go.sum b/go.sum index a4c9cc1927..edb1ec05f6 100644 --- a/go.sum +++ b/go.sum @@ -541,8 +541,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= -github.com/florianl/go-tc v0.4.5 h1:8lvecARs3c/vGee46j0ro8kco98ga9XjwWvXGwlzrXA= -github.com/florianl/go-tc v0.4.5/go.mod h1:uvp6pIlOw7Z8hhfnT5M4+V1hHVgZWRZwwMS8Z0JsRxc= +github.com/florianl/go-tc v0.4.8 h1:hgmakUX1Nm0Ba1I0ZkbUl9CH6HbRwqSiwipnpmYp3Es= +github.com/florianl/go-tc v0.4.8/go.mod h1:B8GeOEnmrbOnxZtaCvsYJcgIzzmM8c/AIhtfCZsDj3Q= github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -1071,11 +1071,11 @@ github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnN github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys= github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= -github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= +github.com/mdlayher/netlink v1.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU= github.com/mdlayher/netlink v1.10.0 h1:K7NHm0iQh2nOtfsj/YNNSN1s7T5JGtNCNwP66OKNiEw= github.com/mdlayher/netlink v1.10.0/go.mod h1:YBnl5BXsCoRuwBjKKlZ+aYmEoq0r12FDA/3JC+94KDg= github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= -github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= +github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= @@ -1655,6 +1655,7 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1673,11 +1674,10 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= @@ -1700,6 +1700,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -1749,13 +1750,13 @@ golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From b5d8d306edcb99ff3b5f228c10b87055e441b567 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:57:02 -0400 Subject: [PATCH 311/448] deps: bump go.uber.org/zap from 1.27.0 to 1.27.1 (#2191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.27.0 to 1.27.1.
Release notes

Sourced from go.uber.org/zap's releases.

v1.27.1

Enhancements:

  • #1501[]: prevent Object from panicking on nils
  • #1511[]: Fix a race condition in WithLazy.

Thanks to @​rabbbit, @​alshopov, @​jquirke, @​arukiidou for their contributions to this release.

#1501: uber-go/zap#1501 #1511: uber-go/zap#1511

Changelog

Sourced from go.uber.org/zap's changelog.

1.27.1 (19 Nov 2025)

Enhancements:

  • #1501[]: prevent Object from panicking on nils
  • #1511[]: Fix a race condition in WithLazy.

Thanks to @​rabbbit, @​alshopov, @​jquirke, @​arukiidou for their contributions to this release.

#1501: uber-go/zap#1501 #1511: uber-go/zap#1511

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +----- go.sum | 12 ++---------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 4879c66f0a..3ed9620210 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.23.0 github.com/spf13/cobra v1.10.1 - go.uber.org/zap v1.27.0 + go.uber.org/zap v1.27.1 k8s.io/client-go v0.32.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 @@ -109,7 +109,6 @@ require ( github.com/go-openapi/validate v0.24.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 // indirect @@ -151,7 +150,6 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect - github.com/moby/moby v26.1.0+incompatible // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect @@ -178,7 +176,6 @@ require ( github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/spiffe/spire-api-sdk v1.12.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -273,7 +270,6 @@ require ( github.com/google/gopacket v1.1.19 github.com/gopacket/gopacket v1.5.0 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/inspektor-gadget/inspektor-gadget v0.27.0 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 github.com/mdlayher/netlink v1.10.0 diff --git a/go.sum b/go.sum index edb1ec05f6..1eec31fc15 100644 --- a/go.sum +++ b/go.sum @@ -673,8 +673,6 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -872,8 +870,6 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/inspektor-gadget/inspektor-gadget v0.27.0 h1:f28khEROUBkKVShlyXOT3sN8T68WZLn6AqRp0aZmUzM= -github.com/inspektor-gadget/inspektor-gadget v0.27.0/go.mod h1:26ArCiACp1/3lfF6RymrznxBDfuPXYgvyk0dJEhFMVI= github.com/inspektor-gadget/netns v0.0.5-0.20230524185006-155d84c555d6 h1:fQqkJ+WkYfzy6BoUh32fr9uYrXfOGtsfw0skMQkfOic= github.com/inspektor-gadget/netns v0.0.5-0.20230524185006-155d84c555d6/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= @@ -1104,8 +1100,6 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/moby v26.1.0+incompatible h1:mjepCwMH0KpCgPvrXjqqyCeTCHgzO7p9TwZ2nQMI2qU= -github.com/moby/moby v26.1.0+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= @@ -1407,8 +1401,6 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= @@ -1591,8 +1583,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= From bdb2eb729538eebf2238dbf4f2df9a8f6db9e5fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 00:50:27 -0400 Subject: [PATCH 312/448] chore(deps): bump follow-redirects from 1.15.11 to 1.16.0 in /site in the npm_and_yarn group across 1 directory (#2197) Bumps the npm_and_yarn group with 1 update in the /site directory: [follow-redirects](https://github.com/follow-redirects/follow-redirects). Updates `follow-redirects` from 1.15.11 to 1.16.0
Commits
  • 0c23a22 Release version 1.16.0 of the npm package.
  • 844c4d3 Add sensitiveHeaders option.
  • 5e8b8d0 ci: add Node.js 24.x to the CI matrix
  • 7953e22 ci: upgrade GitHub Actions to use setup-node@v6 and checkout@v6
  • 86dc1f8 Sanitizing input.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.11&new-version=1.16.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 2e2a6afa85..470c8575a1 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -170,7 +170,6 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/client-common": "5.48.1", "@algolia/requester-browser-xhr": "5.48.1", @@ -296,7 +295,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2101,7 +2099,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2124,7 +2121,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2234,7 +2230,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2656,7 +2651,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3749,7 +3743,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/logger": "3.9.2", @@ -4862,7 +4855,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5162,7 +5154,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5528,7 +5519,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -5873,7 +5863,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5940,7 +5929,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5986,7 +5974,6 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/abtesting": "1.14.1", "@algolia/client-abtesting": "5.48.1", @@ -6596,7 +6583,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7616,7 +7602,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9137,7 +9122,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -9267,9 +9251,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -13766,7 +13750,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14342,7 +14325,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15216,7 +15198,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -16081,7 +16062,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16094,7 +16074,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -16147,7 +16126,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -16174,7 +16152,6 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17326,7 +17303,6 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, - "peer": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -18267,8 +18243,7 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "peer": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18340,7 +18315,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18696,7 +18670,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -18892,7 +18865,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", From 53e0b0ab8b293f7d485226abe32edf94aa76b397 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:50:11 +0000 Subject: [PATCH 313/448] deps: bump github.com/Microsoft/hcsshim from 0.13.0 to 0.14.1 (#2200) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.13.0 to 0.14.1.
Release notes

Sourced from github.com/Microsoft/hcsshim's releases.

v0.14.1

What's Changed

fb5aa2e94 - Maksim An (2026-04-07): upgrade dependencies to fix CI 9a434d6e1 - Dawei Wei (2026-03-06): shim: skip SandboxPlatform validation when platform is not explicitly set (#2620) 98d74bb52 - Cory Snider (2026-02-10): WCOW: restore support for client-mounted roots (#2595)

Full Changelog: https://github.com/microsoft/hcsshim/compare/v0.14.0...v0.14.1

v0.14.0

This is a non-rc v0.14.0 release, which is the same as https://github.com/microsoft/hcsshim/releases/tag/v0.14.0-rc.1

What's Changed

Full Changelog: https://github.com/microsoft/hcsshim/compare/v0.13.0...v0.14.0

v0.14.0-rc.1

What's Changed

... (truncated)

Commits
  • fb5aa2e upgrade dependencies to fix CI
  • 9a434d6 shim: skip SandboxPlatform validation when platform is not explicitly set (#2...
  • 98d74bb WCOW: restore support for client-mounted roots (#2595)
  • 59e0e2f Bump actions/checkout from 4 to 5 (#2499)
  • a776109 Fix console size bug
  • 0366cb2 Add default allow all policy to uvmboot
  • 144c633 Fix CUDA for non-privileged containers (#2492)
  • 0842153 Warn on incomplete vNUMA setting, clarify field names (#2466)
  • 1ee5fce Merge pull request #2456 from ambarve/hyperv_bcims
  • a2229bf Make a common utility function for appending VHD footer
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Microsoft/hcsshim&package-manager=go_modules&previous-version=0.13.0&new-version=0.14.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 3ed9620210..c48be0d33b 100644 --- a/go.mod +++ b/go.mod @@ -67,11 +67,11 @@ require ( github.com/cilium/lumberjack/v2 v2.4.1 // indirect github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/containerd/cgroups/v3 v3.0.3 // indirect + github.com/containerd/cgroups/v3 v3.0.5 // indirect github.com/containerd/containerd v1.7.29 // indirect - github.com/containerd/errdefs v0.3.0 // indirect + github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/containerd/typeurl/v2 v2.2.0 // indirect + github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/containernetworking/cni v1.2.3 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -157,7 +157,7 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.2-0.20180312054125-0646ccaebea1+incompatible // indirect @@ -253,7 +253,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 - github.com/Microsoft/hcsshim v0.13.0 + github.com/Microsoft/hcsshim v0.14.1 github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.41.5 github.com/aws/aws-sdk-go-v2/config v1.31.6 @@ -306,7 +306,7 @@ require ( github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/cilium/statedb v0.3.7 github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect + github.com/containerd/platforms v1.0.0-rc.1 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/google/cel-go v0.24.1 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect diff --git a/go.sum b/go.sum index 1eec31fc15..6d4fd3dcd0 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA= -github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok= +github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= +github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= 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/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= @@ -413,27 +413,27 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= -github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= -github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= +github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= +github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE= github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs= -github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= -github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= -github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= -github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +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/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= +github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= -github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= +github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= +github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -1104,12 +1104,12 @@ github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= 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/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= 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/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= -github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +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/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -1192,8 +1192,8 @@ github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= 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.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19oYB80= github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= From e30cfb3282aa59a448b95d5443f61f0fff124b8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 19:17:27 -0400 Subject: [PATCH 314/448] deps: bump github/codeql-action from 4.35.1 to 4.35.2 (#2199) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.1 to 4.35.2.
Release notes

Sourced from github/codeql-action's releases.

v4.35.2

  • The undocumented TRAP cache cleanup feature that could be enabled using the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the trap-caching: false input to the init Action. #3795
  • The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. #3789
  • Python analysis on GHES no longer extracts the standard library, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. #3794
  • Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. #3807
  • Update default CodeQL bundle version to 2.25.2. #3823
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.35.2 - 15 Apr 2026

  • The undocumented TRAP cache cleanup feature that could be enabled using the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the trap-caching: false input to the init Action. #3795
  • The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. #3789
  • Python analysis on GHES no longer extracts the standard library, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. #3794
  • Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. #3807
  • Update default CodeQL bundle version to 2.25.2. #3823

4.35.1 - 27 Mar 2026

4.35.0 - 27 Mar 2026

4.34.1 - 20 Mar 2026

  • Downgrade default CodeQL bundle version to 2.24.3 due to issues with a small percentage of Actions and JavaScript analyses. #3762

4.34.0 - 20 Mar 2026

  • Added an experimental change which disables TRAP caching when improved incremental analysis is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. #3569
  • We are rolling out improved incremental analysis to C/C++ analyses that use build mode none. We expect this rollout to be complete by the end of April 2026. #3584
  • Update default CodeQL bundle version to 2.25.0. #3585

4.33.0 - 16 Mar 2026

  • Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. #3562

    To opt out of this change:

    • Repositories owned by an organization: Create a custom repository property with the name github-codeql-file-coverage-on-prs and the type "True/false", then set this property to true in the repository's settings. For more information, see Managing custom properties for repositories in your organization. Alternatively, if you are using an advanced setup workflow, you can set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using default setup: Switch to an advanced setup workflow and set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using advanced setup: Set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
  • Fixed a bug which caused the CodeQL Action to fail loading repository properties if a "Multi select" repository property was configured for the repository. #3557

  • The CodeQL Action now loads custom repository properties on GitHub Enterprise Server, enabling the customization of features such as github-codeql-disable-overlay that was previously only available on GitHub.com. #3559

  • Once private package registries can be configured with OIDC-based authentication for organizations, the CodeQL Action will now be able to accept such configurations. #3563

  • Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". #3564

  • A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. #3570

4.32.6 - 05 Mar 2026

... (truncated)

Commits
  • 95e58e9 Merge pull request #3824 from github/update-v4.35.2-d2e135a73
  • 6f31bfe Update changelog for v4.35.2
  • d2e135a Merge pull request #3823 from github/update-bundle/codeql-bundle-v2.25.2
  • 60abb65 Add changelog note
  • 5a0a562 Update default bundle to codeql-bundle-v2.25.2
  • 6521697 Merge pull request #3820 from github/dependabot/github_actions/dot-github/wor...
  • 3c45af2 Merge pull request #3821 from github/dependabot/npm_and_yarn/npm-minor-345b93...
  • f1c3393 Rebuild
  • 1024fc4 Rebuild
  • 9dd4cfe Bump the npm-minor group across 1 directory with 6 updates
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.35.1&new-version=4.35.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 0ea1f22e50..24c96172c1 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index f2b5add2bd..f84580c205 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: sarif_file: "trivy-results.sarif" From 0fa222dba66b91481456300d6ba874c2742514d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Larivi=C3=A8re?= Date: Thu, 16 Apr 2026 13:01:17 -0400 Subject: [PATCH 315/448] fix: convert hubble-generate-certs ClusterRole to Role to enforce least privilege (#2202) # Description Convert `hubble-generate-certs` ClusterRole to Role to enforce least privilege ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .../hubble/tls-cronjob/{clusterrole.yaml => role.yaml} | 3 ++- .../helm/retina/templates/hubble/tls-cronjob/rolebinding.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/{clusterrole.yaml => role.yaml} (94%) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/clusterrole.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/role.yaml similarity index 94% rename from deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/clusterrole.yaml rename to deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/role.yaml index 74d0783173..cf36be7d19 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/clusterrole.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/role.yaml @@ -1,8 +1,9 @@ {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.serviceAccounts.hubblecertgen.create }} apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: name: hubble-generate-certs + namespace: {{ .Release.Namespace }} {{- with .Values.hubble.annotations }} annotations: {{- toYaml . | nindent 4 }} diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/rolebinding.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/rolebinding.yaml index eca15c6f7d..f25156969d 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/rolebinding.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/hubble/tls-cronjob/rolebinding.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/part-of: cilium roleRef: apiGroup: rbac.authorization.k8s.io - kind: ClusterRole + kind: Role name: hubble-generate-certs subjects: - kind: ServiceAccount From f3de68f8786583ef73b618b06b1538ff90ba1bc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:56:27 -0400 Subject: [PATCH 316/448] deps: bump devcontainers/ci from 0.3.1900000417 to 0.3.1900000449 (#2207) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [devcontainers/ci](https://github.com/devcontainers/ci) from 0.3.1900000417 to 0.3.1900000449.
Release notes

Sourced from devcontainers/ci's releases.

Release v0.3.1900000449

What's Changed

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=devcontainers/ci&package-manager=github_actions&previous-version=0.3.1900000417&new-version=0.3.1900000449)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/devcontainer.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/devcontainer.yaml b/.github/workflows/devcontainer.yaml index cdcba16086..77161f5e39 100644 --- a/.github/workflows/devcontainer.yaml +++ b/.github/workflows/devcontainer.yaml @@ -28,7 +28,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Build and validate devcontainer - uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 # v0.3.1900000417 + uses: devcontainers/ci@b63b30de439b47a52267f241112c5b453b673db5 # v0.3.1900000449 with: runCmd: | clang --version From 2a55ce008147619e730c453b9115dfd356a8a350 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Fri, 17 Apr 2026 19:04:50 +0100 Subject: [PATCH 317/448] fix(dropreason): handle inet_csk_accept signature change on Linux 6.10+ (#2206) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem Closes #1906 Linux 6.10-rc1 ([torvalds/linux@92ef0fd](https://github.com/torvalds/linux/commit/92ef0fd55ac80dfc2e4654edfe5d1ddfa6e070fe)) changed the signature of `inet_csk_accept` from: ```c struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern) ``` to: ```c struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg) ``` This causes the BPF verifier to reject the Retina dropreason `fexit` program on kernels ≥ 6.10 because it declares 4 typed parameters for a function that now only has 2. As a result, the dropreason plugin fails to load on any node running kernel 6.10+. ## Solution Use **BPF CO-RE** (Compile Once – Run Everywhere) to handle both the old and new signatures at runtime: 1. **CO-RE flavor struct** — Define `proto_accept_arg___new` with `preserve_access_index`. The `___new` suffix is stripped during BTF type lookup, so `bpf_core_type_exists()` checks for `proto_accept_arg` in the running kernel's BTF. 2. **kprobe handler** — Remove typed params from `BPF_KPROBE(inet_csk_accept)`. Use `bpf_core_type_exists()` to branch: - **6.10+**: read `err` as an inline field offset inside `proto_accept_arg` (param 2) - **Pre-6.10**: read `err` directly from register param 3 3. **fexit handler** — Remove typed params from `BPF_PROG(inet_csk_accept_fexit)` and read `retsk` from the raw tracing context at the correct slot: - **6.10+**: 2 params → `retsk` at `ctx[2]` - **Pre-6.10**: 4 params → `retsk` at `ctx[4]` Each branch is kept fully self-contained (no merging into a ternary/select) to avoid a verifier rejection on variable-offset ctx access. 4. **Correctness fix** — The old fexit handler unconditionally called `update_metrics_map_basic(TCP_ACCEPT_BASIC, ...)` even when the accept succeeded (`retsk != NULL`). The new code only reports a drop metric when `retsk` is `NULL`, matching the intended "failed accept" semantics. ## Validation Tested on an Azure VM running Ubuntu 24.04 with HWE kernel **6.17.0-1011-azure** using a kind cluster: - All eBPF programs attach successfully, including `inet_csk_accept_fexit` - Drop reason metrics are collected and exposed: image ## Related Issue Fixes #1906 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed (See above) ## Additional Notes - We need to improve the testing infra / automation to test different kernels, created #2205 --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Simone Rodigari --- pkg/plugin/dropreason/_cprog/drop_reason.c | 52 +++++++++++++++++----- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/pkg/plugin/dropreason/_cprog/drop_reason.c b/pkg/plugin/dropreason/_cprog/drop_reason.c index c716157857..ee2cbc770b 100644 --- a/pkg/plugin/dropreason/_cprog/drop_reason.c +++ b/pkg/plugin/dropreason/_cprog/drop_reason.c @@ -12,6 +12,19 @@ #include "dynamic.h" #include "retina_filter.c" +// CO-RE flavor struct for Linux 6.10+ where inet_csk_accept changed signature from +// (struct sock *sk, int flags, int *err, bool kern) to +// (struct sock *sk, struct proto_accept_arg *arg). +// The ___new suffix is stripped during BTF type lookup, so bpf_core_type_exists() +// checks for 'proto_accept_arg' in the running kernel's BTF. +// https://github.com/torvalds/linux/commit/92ef0fd55ac80dfc2e4654edfe5d1ddfa6e070fe +struct proto_accept_arg___new { + int flags; + int err; + int is_empty; + bool kern; +} __attribute__((preserve_access_index)); + char __license[] SEC("license") = "Dual MIT/GPL"; #define ETH_P_IP 0x0800 @@ -358,7 +371,7 @@ int BPF_PROG(tcp_v4_connect_fexit, struct sock *sk, struct sockaddr *uaddr, int } SEC("kprobe/inet_csk_accept") -int BPF_KPROBE(inet_csk_accept, struct sock *sk, int flags, int *err, bool kern) +int BPF_KPROBE(inet_csk_accept) { /* This function will save the reference value to error. @@ -366,7 +379,20 @@ int BPF_KPROBE(inet_csk_accept, struct sock *sk, int flags, int *err, bool kern) */ __u64 pid_tgid = bpf_get_current_pid_tgid(); __u32 pid = pid_tgid >> 32; - __u64 err_ptr = (__u64)err; + + __u64 err_ptr = 0; + + // Linux 6.10+: inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg) + // err is an inline int field inside proto_accept_arg. + if (bpf_core_type_exists(struct proto_accept_arg___new)) { + struct proto_accept_arg___new *arg = (struct proto_accept_arg___new *)PT_REGS_PARM2(ctx); + err_ptr = (__u64)&arg->err; + } else { + // Pre-6.10: inet_csk_accept(struct sock *sk, int flags, int *err, bool kern) + int *err = (int *)PT_REGS_PARM3(ctx); + err_ptr = (__u64)err; + } + bpf_map_update_elem(&retina_dropreason_accept_pids, &pid, &err_ptr, BPF_ANY); return 0; } @@ -415,17 +441,23 @@ int BPF_KRETPROBE(inet_csk_accept_ret, struct sock *sk) } SEC("fexit/inet_csk_accept") -int BPF_PROG(inet_csk_accept_fexit, struct sock *sk, int flags, int *err, struct sock *retsk) +int BPF_PROG(inet_csk_accept_fexit) { - if (retsk != NULL) { - return 0; + // Each branch must be fully self-contained so the compiler generates a real + // branch instruction. If merged into a select, the verifier rejects the + // variable-offset ctx access ("dereference of modified ctx ptr"). + // + // fexit ctx layout: [param1, param2, ..., paramN, return_value] + // Linux 6.10+: 2 params (sk, arg) -> retsk at ctx[2] + // Pre-6.10: 4 params (sk, flags, err, kern) -> retsk at ctx[4] + if (bpf_core_type_exists(struct proto_accept_arg___new)) { + if ((struct sock *)ctx[2] == NULL) + update_metrics_map_basic(TCP_ACCEPT_BASIC, 0, 0); + } else { + if ((struct sock *)ctx[4] == NULL) + update_metrics_map_basic(TCP_ACCEPT_BASIC, 0, 0); } - // TODO - // Pass 0 packet length - get_packet_from_sock above doesn't obtain this value, either. - // Pass 0 return value; verifier failure, same as buggy kprobe above. - update_metrics_map_basic(TCP_ACCEPT_BASIC, 0, 0); - return 0; } From 98b65c671b7e7598fa93e14ea0a825f433fabda0 Mon Sep 17 00:00:00 2001 From: Kelvin Oppong Acheampong Date: Fri, 17 Apr 2026 18:10:40 -0500 Subject: [PATCH 318/448] fix: widen API server latency histogram buckets for large clusters (#2198) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Fixes #82 — API Server Latency buckets are skewed in large scale clusters. The previous histogram bucket configuration (`start=0, width=0.5ms, count=10`) produced buckets: `0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, +Inf` (ms). In large clusters, API server latencies routinely exceed 4.5ms, causing all observations to land in the `+Inf` bucket and making the histogram unusable. ### Changes - Start at 0.5ms instead of 0ms (removes useless 0ms bucket) - Use 1ms bucket width instead of 0.5ms (wider coverage) - Increase count from 10 to 64, covering up to 63.5ms New buckets: `0.5, 1.5, 2.5, ..., 63.5, +Inf` (ms) ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. ## Testing Completed All existing latency tests pass: - `TestNewLatencyMetrics` — PASS - `TestInit` — PASS - `TestProcessFlow` — PASS Signed-off-by: Kelvin --- pkg/module/metrics/latency.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/module/metrics/latency.go b/pkg/module/metrics/latency.go index ee14c9dbd2..0fb88ec7b9 100644 --- a/pkg/module/metrics/latency.go +++ b/pkg/module/metrics/latency.go @@ -33,10 +33,11 @@ const ( apiServerHandshakeLatencyDesc = "Latency of node apiserver tcp handshake in ms" TTL time.Duration = 500 * time.Millisecond LIMIT uint64 = 100000 - // Bucket size. - start = 0 - width = 0.5 - count = 10 + // Histogram bucket parameters (units: milliseconds). + // Produces buckets: 0.5, 1.5, 2.5, ..., 63.5, +Inf. + start = 0.5 + width = 1 + count = 64 ) type key struct { From def528d9fb9e3c3037aed7255d7f618192baf2cc Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Mon, 20 Apr 2026 12:56:20 -0400 Subject: [PATCH 319/448] deps(cilium): upgrade Cilium to v1.19.3 (#2148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Upgrade Cilium from v1.18.0-pre.1 to v1.19.3 and adapt the codebase for all breaking API changes. This PR is now a single squashed commit covering the dependency upgrade and all required adaptations. The DNS and tcpretrans plugin rewrites that were previously part of this branch have already been merged separately (#2152, #2153). ## Changes by area **Logging (logrus → slog)** - Add zap-backed `slog.Handler` and `logr.Logger` bridges in `pkg/log/zap.go` with thread-safe init via `sync.Once` - Migrate all DI-injected loggers from `logrus.FieldLogger` to `*slog.Logger` across agent, operator, and Hubble components - `InitializeMetrics()` now takes `*slog.Logger` with nil-safety guard - Wire `SetDefaultSlog()` at startup so `slog.Default()` routes through zap → Application Insights **Hubble control plane** - Adapt to v1.19 Hive cell changes: remove `ServiceCache` cell (replaced by frontends table), update `InitK8sSubsystem` signature, replace `NoOpOrchestrator` with `fakedp.FakeOrchestrator` - Set `IdentityUpdater` in IPCache config to prevent nil-panic on label injection paths - Remove `skipUnknownCGroupIDs` parameter from Hubble parser constructor (removed in v1.19) - DI cell broken into sub-cells for fault isolation **Operator** - Migrate CRD helpers to v1.19 API (`CreateUpdateCRD`, `GetPregeneratedCRD` now take `*slog.Logger`) - Replace local resource constructors with imports from `cilium/operator/k8s` behind `_linux` build tag - Add in-memory kvstore client for identity GC cell - Remove obsolete KVstore flag registrations **Build & CI** - Update golangci-lint tool path and CI workflow for v2 - Remove orphaned `ITracer` mock (`pkg/plugin/common/mocks/`) ## Related Issue Fixes #1788 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Testing Completed - Deployed to AKS cluster (`retinaTest-v119`) with Hubble mode, all 3 agent pods + operator healthy (1/1) image - Application Insights telemetry verified: 536+ traces ingested via slog → zap → zapai pipeline, all severity levels (INFO/WARN/ERROR) flowing with correct structured fields (module, plugin, appInsightsID) image - Prometheus Hubble metrics endpoint serving on `:9965/metrics` image - All eBPF plugins started successfully: dropreason, dns, tcpretrans, packetforward, packetparser, linuxutil - Hubble relay and UI running with `quay.io/cilium/` v1.19.3 images image image - `go build ./...`, `make lint` (0 issues), unit tests all pass Signed-off-by: Quang Nguyen --- .github/workflows/golangci-lint.yaml | 2 +- Makefile | 2 +- cmd/hubble/cells_linux.go | 78 +- cmd/hubble/daemon_linux.go | 29 +- cmd/hubble/daemon_main_linux.go | 84 +- cmd/standard/daemon.go | 10 +- .../retina/templates/agent/daemonset.yaml | 4 +- go.mod | 622 +++---- go.sum | 1444 +++++++++-------- operator/cilium-crds/k8s/apis/cell.go | 4 +- operator/cilium-crds/k8s/apis/register.go | 6 +- ...{fakeresource.go => fakeresource_linux.go} | 3 +- operator/cilium-crds/k8s/resource_ctors.go | 62 - .../cilium-crds/k8s/resource_ctors_linux.go | 18 + .../k8s/{resources.go => resources_linux.go} | 6 +- operator/cmd/cilium-crds/cells_linux.go | 17 +- operator/cmd/cilium-crds/flags.go | 6 +- operator/cmd/cilium-crds/root_linux.go | 88 +- operator/cmd/cilium-crds/zap_linux.go | 67 +- operator/cmd/cilium_crds_cmd_linux.go | 3 +- operator/cmd/standard/deployment.go | 15 +- pkg/common/endpoint.go | 4 +- pkg/config/hubble_config_linux.go | 8 +- .../daemon/nodereconciler/cell_linux.go | 6 +- .../nodereconciler/node_controller_linux.go | 6 - .../endpoint/endpoint_controller_linux.go | 175 +- .../endpoint_controller_linux_test.go | 9 +- .../endpoint/identitymanager_linux.go | 64 +- .../endpoint/identitymanager_linux_test.go | 50 +- .../retinaendpoint_controller_test.go | 15 +- pkg/hubble/parser/layer34/parser_linux.go | 15 +- pkg/hubble/parser/parser_linux.go | 17 +- pkg/hubble/parser/seven/parser_linux.go | 15 +- pkg/k8s/apiserver_linux.go | 30 +- pkg/k8s/cell_linux.go | 337 ++-- pkg/k8s/local_node_synchronizer_linux.go | 4 +- pkg/k8s/placeholders_linux.go | 142 +- pkg/k8s/watcher_linux.go | 38 +- pkg/log/export_test.go | 13 + pkg/log/zap.go | 187 ++- pkg/log/zap_test.go | 72 +- .../controllermanager/controllermanager.go | 19 +- .../controllermanager_test.go | 11 +- pkg/managers/pluginmanager/cells_linux.go | 14 +- pkg/managers/pluginmanager/pluginmanager.go | 25 +- .../pluginmanager/pluginmanager_test.go | 23 +- pkg/metrics/metrics.go | 10 +- pkg/metrics/metrics_test.go | 7 +- pkg/metrics/types.go | 10 +- pkg/module/metrics/dns_test.go | 3 +- pkg/module/metrics/drops_test.go | 3 +- pkg/module/metrics/forward_test.go | 3 +- pkg/module/metrics/tcpflags_test.go | 3 +- pkg/monitoragent/cell_linux.go | 18 +- pkg/monitoragent/monitoragent_linux.go | 32 +- .../ciliumeventobserver_linux_test.go | 3 + .../ciliumeventobserver/parser_linux.go | 1 - pkg/plugin/common/common_linux.go | 13 +- pkg/plugin/common/mocks/mock_types.go | 91 -- pkg/plugin/dns/dns_linux_test.go | 3 +- .../dropreason/dropreason_linux_test.go | 3 +- .../packetforward/packetforward_linux_test.go | 7 +- .../tcpretrans/tcpretrans_linux_test.go | 3 +- pkg/servermanager/cell_linux.go | 10 +- pkg/shared/telemetry/cell_linux.go | 14 +- pkg/utils/flow_utils.go | 41 +- pkg/utils/testutil/cilium/endpoint_client.go | 9 +- pkg/utils/testutil/cilium/identity_client.go | 7 +- pkg/utils/testutil/cilium/resource.go | 6 +- pkg/utils/testutil/cilium/versioned_client.go | 20 +- pkg/utils/utils_linux_test.go | 2 - test/managers/filtermanager/main.go | 3 +- test/plugin/dns/main_linux.go | 3 +- test/plugin/dropreason/main_linux.go | 3 +- test/plugin/infiniband/main_linux.go | 3 +- test/plugin/linuxutil/main_linux.go | 3 +- test/plugin/packetforward/main_linux.go | 3 +- test/plugin/packetparser/main_linux.go | 3 +- 78 files changed, 2244 insertions(+), 1968 deletions(-) rename operator/cilium-crds/k8s/{fakeresource.go => fakeresource_linux.go} (90%) delete mode 100644 operator/cilium-crds/k8s/resource_ctors.go create mode 100644 operator/cilium-crds/k8s/resource_ctors_linux.go rename operator/cilium-crds/k8s/{resources.go => resources_linux.go} (96%) create mode 100644 pkg/log/export_test.go delete mode 100644 pkg/plugin/common/mocks/mock_types.go diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 1cab442154..a1d2202fb8 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -35,7 +35,7 @@ jobs: with: go-version-file: go.mod - name: Build golangci-lint - run: GOOS=linux GOARCH=amd64 go build -o "$RUNNER_TEMP/golangci-lint" github.com/golangci/golangci-lint/cmd/golangci-lint + run: GOOS=linux GOARCH=amd64 go build -o "$RUNNER_TEMP/golangci-lint" github.com/golangci/golangci-lint/v2/cmd/golangci-lint - name: golangci-lint run: | "$RUNNER_TEMP/golangci-lint" run --new-from-rev=${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before || 'HEAD~1' }} --concurrency 4 --verbose --config=.golangci.yaml --timeout=25m diff --git a/Makefile b/Makefile index 90d1254d66..33ab104065 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ help: ## Display this help ##@ Tools GOFUMPT = go tool mvdan.cc/gofumpt -GOLANGCI_LINT = go tool github.com/golangci/golangci-lint/cmd/golangci-lint +GOLANGCI_LINT = go tool github.com/golangci/golangci-lint/v2/cmd/golangci-lint GORELEASER = go tool github.com/goreleaser/goreleaser CONTROLLER_GEN = go tool sigs.k8s.io/controller-tools/cmd/controller-gen GINKGO = go tool github.com/onsi/ginkgo diff --git a/cmd/hubble/cells_linux.go b/cmd/hubble/cells_linux.go index be67848cb4..dd05e51aed 100644 --- a/cmd/hubble/cells_linux.go +++ b/cmd/hubble/cells_linux.go @@ -5,18 +5,24 @@ package hubble import ( + "log/slog" + "sync" + + "github.com/cilium/cilium/pkg/datapath/link" "github.com/cilium/cilium/pkg/defaults" "github.com/cilium/cilium/pkg/gops" hubblecell "github.com/cilium/cilium/pkg/hubble/cell" - exportercell "github.com/cilium/cilium/pkg/hubble/exporter/cell" + metricscell "github.com/cilium/cilium/pkg/hubble/metrics/cell" + ciliumparser "github.com/cilium/cilium/pkg/hubble/parser" k8sClient "github.com/cilium/cilium/pkg/k8s/client" - "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/kpr" + "github.com/cilium/cilium/pkg/kvstore" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/node/manager" "github.com/cilium/cilium/pkg/option" "github.com/cilium/cilium/pkg/pprof" - "github.com/cilium/cilium/pkg/recorder" "github.com/cilium/hive/cell" + "github.com/cilium/statedb" "k8s.io/client-go/rest" "github.com/microsoft/retina/internal/buildinfo" @@ -25,12 +31,43 @@ import ( "github.com/microsoft/retina/pkg/hubble/parser" "github.com/microsoft/retina/pkg/hubble/resources" retinak8s "github.com/microsoft/retina/pkg/k8s" + retinalog "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/managers/pluginmanager" "github.com/microsoft/retina/pkg/monitoragent" "github.com/microsoft/retina/pkg/servermanager" "github.com/microsoft/retina/pkg/shared/telemetry" ) +// disabledKVStoreClient wraps a kvstore.Client but returns IsEnabled() = false. +// This is needed because K8sCiliumEndpointsWatcher only initializes if kvstore is disabled. +// When kvstore is enabled, Cilium expects CiliumEndpoint data to come from kvstore, +// but Retina watches CiliumEndpoint CRDs directly and needs the watcher to populate IPCache. +type disabledKVStoreClient struct { + kvstore.Client +} + +// IsEnabled returns false to indicate kvstore is not being used for CiliumEndpoint sync. +// This allows the K8sCiliumEndpointsWatcher to initialize and populate IPCache with K8sMetadata. +func (d *disabledKVStoreClient) IsEnabled() bool { + return false +} + +const daemonSubsys = "daemon" + +var ( + loggerOnce sync.Once + cachedLogger *slog.Logger +) + +// logger returns a zap-backed slog logger. Resolved lazily so it reaches +// Application Insights once SetupZapLogger has run. +func logger() *slog.Logger { + loggerOnce.Do(func() { + cachedLogger = retinalog.SlogLogger().With(logfields.LogSubsys, daemonSubsys) + }) + return cachedLogger +} + var ( Agent = cell.Module( "agent", @@ -38,8 +75,6 @@ var ( Infrastructure, ControlPlane, ) - daemonSubsys = "daemon" - logger = logging.DefaultLogger.WithField(logfields.LogSubsys, daemonSubsys) Infrastructure = cell.Module( "infrastructure", @@ -61,6 +96,19 @@ var ( // Kubernetes client k8sClient.Cell, + // Kube proxy replacement config (needed by loadbalancer cells) + kpr.Cell, + + // Provide a disabled kvstore client for Retina. + // This is important: the K8sCiliumEndpointsWatcher only initializes + // if kvstore.IsEnabled() returns false (because with a real kvstore, + // CiliumEndpoint data would come from kvstore instead of watching CRDs). + // Since Retina doesn't use etcd/consul and relies on watching CiliumEndpoint CRDs, + // we need IsEnabled() to return false so the watcher populates IPCache with K8sMetadata. + cell.Provide(func(db *statedb.DB) kvstore.Client { + return &disabledKVStoreClient{Client: kvstore.NewInMemoryClient(db, "default")} + }), + cell.Provide(func(cfg config.Config, k8sCfg *rest.Config) telemetry.Config { return telemetry.Config{ Component: "retina-agent", @@ -92,11 +140,11 @@ var ( retinak8s.Cell, - recorder.Cell, - // Provides resources for hubble resources.Cell, - cell.Provide(parser.New), + + // Provides link cache needed by hubble parser + link.Cell, // Provides the node reconciler as node manager rnode.Cell, @@ -106,9 +154,17 @@ var ( }, ), - exportercell.Cell, - // Provides the hubble agent - hubblecell.Core, + // Provides the full hubble agent (includes parser, exporter, metrics, and TLS) + hubblecell.Cell, + + // Force the Hubble metrics server to start. Without this, the DI system + // prunes newMetricsServer because nothing in Retina consumes metricscell.Server. + cell.Invoke(func(_ metricscell.Server) {}), + + // Override Cilium's parser with Retina's parser that understands v1.Event from plugins + cell.DecorateAll(func(_ ciliumparser.Decoder, params parser.Params) ciliumparser.Decoder { + return parser.New(params) + }), telemetry.Heartbeat, ) diff --git a/cmd/hubble/daemon_linux.go b/cmd/hubble/daemon_linux.go index 58636e761d..58c281a4a5 100644 --- a/cmd/hubble/daemon_linux.go +++ b/cmd/hubble/daemon_linux.go @@ -7,11 +7,12 @@ package hubble import ( "context" "fmt" + "log/slog" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/microsoft/retina/pkg/config" + "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/managers/pluginmanager" "github.com/microsoft/retina/pkg/managers/servermanager" @@ -20,7 +21,6 @@ import ( v1 "github.com/cilium/cilium/pkg/hubble/api/v1" hubblecell "github.com/cilium/cilium/pkg/hubble/cell" "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" k8sClient "github.com/cilium/cilium/pkg/k8s/client" "github.com/cilium/cilium/pkg/k8s/watchers" monitoragent "github.com/cilium/cilium/pkg/monitor/agent" @@ -34,7 +34,6 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" - zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" ) @@ -44,7 +43,9 @@ var ( "daemon", "Retina-Agent Daemon", // Create the controller manager, provides the hive with the controller manager and its client - cell.Provide(func(k8sCfg *rest.Config, logger logrus.FieldLogger, rcfg config.RetinaHubbleConfig) (ctrl.Manager, client.Client, error) { + cell.Provide(func( + k8sCfg *rest.Config, logger *slog.Logger, rcfg config.RetinaHubbleConfig, + ) (ctrl.Manager, client.Client, error) { if err := corev1.AddToScheme(scheme); err != nil { //nolint:govet // intentional shadow logger.Error("failed to add corev1 to scheme") return nil, nil, errors.Wrap(err, "failed to add corev1 to scheme") @@ -60,7 +61,7 @@ var ( LeaderElectionID: "ecaf1259.retina.io", } - logf.SetLogger(zapf.New()) + logf.SetLogger(log.LogrLogger()) ctrlManager, err := ctrl.NewManager(k8sCfg, mgrOption) if err != nil { logger.Error("failed to create manager") @@ -71,7 +72,7 @@ var ( }), // Start the controller manager - cell.Invoke(func(l logrus.FieldLogger, lifecycle cell.Lifecycle, ctrlManager ctrl.Manager) { + cell.Invoke(func(l *slog.Logger, lifecycle cell.Lifecycle, ctrlManager ctrl.Manager) { var wp *workerpool.WorkerPool lifecycle.Append( cell.Hook{ @@ -99,7 +100,7 @@ var ( type Daemon struct { clientset k8sClient.Clientset - log logrus.FieldLogger + log *slog.Logger monitorAgent monitoragent.Agent pluginManager *pluginmanager.PluginManager HTTPServer *servermanager.HTTPServer @@ -108,7 +109,6 @@ type Daemon struct { k8swatcher *watchers.K8sWatcher localNodeStore *node.LocalNodeStore ipc *ipcache.IPCache - svcCache k8s.ServiceCache hubble hubblecell.HubbleIntegration } @@ -124,17 +124,12 @@ func newDaemon(params *daemonParams) *Daemon { k8swatcher: params.K8sWatcher, localNodeStore: params.Lnds, ipc: params.IPC, - svcCache: params.SvcCache, hubble: params.Hubble, } } func (d *Daemon) Run(ctx context.Context) error { - // Start K8s watcher - d.log.WithField("localNodeStore", d.localNodeStore).Info("Starting local node store") - - // Start K8s watcher. Will block till sync is complete or timeout. - // If sync doesn't complete within timeout (3 minutes), causes fatal error. + // Start K8s watcher. Blocks until sync completes or times out (3 min). retinak8s.Start(ctx, d.k8swatcher) go d.generateEvents(ctx) @@ -147,10 +142,8 @@ func (d *Daemon) generateEvents(ctx context.Context) { case <-ctx.Done(): return case event := <-d.eventChan: - d.log.WithField("event", event).Debug("Sending event to monitor agent") - err := d.monitorAgent.SendEvent(0, event) - if err != nil { - d.log.WithError(err).Error("Unable to send event to monitor agent") + if err := d.monitorAgent.SendEvent(0, event); err != nil { + d.log.Error("Unable to send event to monitor agent", "error", err) } } } diff --git a/cmd/hubble/daemon_main_linux.go b/cmd/hubble/daemon_main_linux.go index e88c195882..ba240a2722 100644 --- a/cmd/hubble/daemon_main_linux.go +++ b/cmd/hubble/daemon_main_linux.go @@ -8,20 +8,17 @@ package hubble import ( "context" "fmt" - "io" "log/slog" - "os" "path/filepath" - zaphook "github.com/Sytten/logrus-zap-hook" "github.com/cilium/cilium/pkg/hive" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" hubblecell "github.com/cilium/cilium/pkg/hubble/cell" "github.com/cilium/cilium/pkg/ipcache" - "github.com/cilium/cilium/pkg/k8s" k8sClient "github.com/cilium/cilium/pkg/k8s/client" "github.com/cilium/cilium/pkg/k8s/watchers" "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/metrics" monitorAgent "github.com/cilium/cilium/pkg/monitor/agent" "github.com/cilium/cilium/pkg/node" @@ -38,7 +35,6 @@ import ( "github.com/microsoft/retina/pkg/managers/servermanager" sharedconfig "github.com/microsoft/retina/pkg/shared/config" "github.com/microsoft/retina/pkg/telemetry" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" "go.uber.org/zap" @@ -64,7 +60,7 @@ func InitGlobalFlags(cmd *cobra.Command, vp *viper.Viper) { vp.Set(option.EndpointGCInterval, 0) if err := vp.BindPFlags(flags); err != nil { - logger.Fatalf("BindPFlags failed: %s", err) + logging.Fatal(logger(), fmt.Sprintf("BindPFlags failed: %s", err)) } } @@ -76,13 +72,12 @@ type daemonParams struct { MonitorAgent monitorAgent.Agent PluginManager *pluginmanager.PluginManager HTTPServer *servermanager.HTTPServer - Log logrus.FieldLogger + Log *slog.Logger Client client.Client EventChan chan *v1.Event K8sWatcher *watchers.K8sWatcher Lnds *node.LocalNodeStore IPC *ipcache.IPCache - SvcCache k8s.ServiceCache Telemetry telemetry.Telemetry Hubble hubblecell.HubbleIntegration Config config.Config @@ -101,7 +96,7 @@ func newDaemonPromise(params daemonParams) promise.Promise[*Daemon] { daemon = d daemonResolver.Resolve(daemon) - d.log.Info("starting Retina Enterprise version: ", buildinfo.Version) + d.log.Info("starting Retina", "version", buildinfo.Version) err := d.Run(daemonCtx) if err != nil { return fmt.Errorf("daemon run failed: %w", err) @@ -117,27 +112,32 @@ func newDaemonPromise(params daemonParams) promise.Promise[*Daemon] { return daemonPromise } -func initLogging() { - logger := setupDefaultLogger() - retinaConfig, _ := getRetinaConfig(logger) +// initZap wires Retina's zap logger (including the Application Insights sink) +// and redirects Go's stdlib slog default at it. The Cilium-side tee must wait +// until *after* logging.SetupLogging runs, because SetupLogging calls +// MultiSlogHandler.SetHandler which replaces the handler list. +func initZap() { + retinaConfig, _ := getRetinaConfig() k8sCfg, _ := sharedconfig.GetK8sConfig() - zapLogger := setupZapLogger(retinaConfig, k8sCfg) - setupLoggingHooks(logger, zapLogger) - bootstrapLogging(retinaConfig, logger) + setupZapLogger(retinaConfig, k8sCfg) + + // Route Go's stdlib slog default through zap so any bare slog call hits AI. + log.SetDefaultSlog() } -func setupDefaultLogger() *logrus.Logger { - logger := logging.DefaultLogger - logger.ReportCaller = true - logger.SetOutput(io.Discard) - return logger +func initLogging() { + bootstrapLogging() + // Register zap + metrics hook AFTER SetupLogging so they survive its + // defaultMultiSlogHandler.SetHandler replace. From this point every + // logging.DefaultSlogLogger emission fans out to zap → Application Insights. + logging.AddHandlers(log.SlogHandler(), metrics.NewLoggingHook()) } -func getRetinaConfig(logger *logrus.Logger) (*config.Config, error) { +func getRetinaConfig() (*config.Config, error) { retinaConfigFile := filepath.Join(option.Config.ConfigDir, configFileName) conf, err := config.GetConfig(retinaConfigFile) if err != nil { - logger.WithError(err).Error("Failed to get config file") + logging.DefaultSlogLogger.Error("Failed to get config file", "error", err) return nil, fmt.Errorf("getting config from file %q: %w", configFileName, err) } return conf, nil @@ -164,7 +164,7 @@ func setupZapLogger(retinaConfig *config.Config, k8sCfg *rest.Config) *log.ZapLo _, err := log.SetupZapLogger(logOpts, persistentFields...) if err != nil { - logger.Fatalf("Failed to setup zap logger: %v", err) + logging.Fatal(logger(), fmt.Sprintf("Failed to setup zap logger: %v", err)) } namedLogger := log.Logger().Named("retina-with-hubble") @@ -173,52 +173,42 @@ func setupZapLogger(retinaConfig *config.Config, k8sCfg *rest.Config) *log.ZapLo return namedLogger } -func setupLoggingHooks(logger *logrus.Logger, zapLogger *log.ZapLogger) { - logger.Hooks.Add(metrics.NewLoggingHook()) - - zapHook, err := zaphook.NewZapHook(zapLogger.Logger) - if err != nil { - logger.WithError(err).Error("Failed to create zap hook") - } else { - logger.Hooks.Add(zapHook) - } -} - -func bootstrapLogging(retinaConfig *config.Config, logger *logrus.Logger) { +func bootstrapLogging() { if err := logging.SetupLogging(option.Config.LogDriver, logging.LogOptions(option.Config.LogOpt), "retina-agent", option.Config.Debug); err != nil { - logger.Fatal(err) - } - - logLevel, err := logrus.ParseLevel(retinaConfig.LogLevel) - if err != nil { - logLevel = logrus.InfoLevel + logging.Fatal(logging.DefaultSlogLogger, err.Error()) } - logger.SetLevel(logLevel) } func initDaemonConfig(vp *viper.Viper) { - option.Config.Populate(vp) + // slogloggercheck: using default logger for configuration initialization + option.Config.Populate(logging.DefaultSlogLogger, vp) time.MaxInternalTimerDelay = vp.GetDuration(option.MaxInternalTimerDelay) } func Execute(cobraCmd *cobra.Command, h *hive.Hive) { - fn := option.InitConfig(cobraCmd, "retina-agent", "retina", h.Viper()) + // slogloggercheck: using default logger for configuration initialization + fn := option.InitConfig(logging.DefaultSlogLogger, cobraCmd, "retina-agent", "retina", h.Viper()) fn() initDaemonConfig(h.Viper()) + + // Bring up zap + Application Insights first, then tee Cilium's slog into it. + // Any subsequent log that flows through Cilium's DefaultSlogLogger (including + // SetupLogging output below) now reaches AI. + initZap() initLogging() - hiveLogger := slog.New(slog.NewTextHandler(os.Stdout, nil)) + hiveLogger := log.SlogLogger() // Allow the current process to lock memory for eBPF resources. if err := rlimit.RemoveMemlock(); err != nil { - logger.Fatal("failed to remove memlock", zap.Error(err)) + logging.Fatal(logger(), "failed to remove memlock", logfields.Error, err) } //nolint:gocritic // without granular commits this commented-out code may be lost // initEnv(h.Viper()) if err := h.Run(hiveLogger); err != nil { - logger.Fatal(err) + logging.Fatal(logger(), "Hive Run failed", logfields.Error, err) } } diff --git a/cmd/standard/daemon.go b/cmd/standard/daemon.go index 2c3194fe41..b93763054e 100644 --- a/cmd/standard/daemon.go +++ b/cmd/standard/daemon.go @@ -4,6 +4,7 @@ package standard import ( "fmt" + "log/slog" "os" "strings" @@ -24,6 +25,7 @@ import ( crmgr "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "github.com/cilium/cilium/pkg/logging" "github.com/go-logr/zapr" retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" "github.com/microsoft/retina/internal/buildinfo" @@ -128,6 +130,10 @@ func (d *Daemon) Start() error { panic(err) } defer zl.Close() + // Tee Cilium's MultiSlogHandler into zap so any DefaultSlogLogger call + // (including package-var captures) reaches Application Insights. + logging.AddHandlers(log.SlogHandler()) + log.SetDefaultSlog() // Set Go's global slog to use zap-backed handler mainLogger := zl.Named("main").Sugar() // Allow the current process to lock memory for eBPF resources. @@ -137,7 +143,7 @@ func (d *Daemon) Start() error { mainLogger.Fatal("failed to remove memlock", zap.Error(err)) } - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) mainLogger.Info(zap.String("data aggregation level", daemonConfig.DataAggregationLevel.String())) @@ -294,7 +300,7 @@ func (d *Daemon) Start() error { } } - controllerMgr, err := cm.NewControllerManager(daemonConfig, cl, tel) + controllerMgr, err := cm.NewControllerManager(daemonConfig, cl, tel, slog.Default()) if err != nil { mainLogger.Fatal("Failed to create controller manager", zap.Error(err)) } diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml index 6e5fe415ae..99eec33c6d 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/daemonset.yaml @@ -126,7 +126,7 @@ spec: - name: cilium mountPath: /var/run/cilium - name: host-os-release - mountPath: /etc/os-release + mountPath: /etc/os-release - name: tmp mountPath: /tmp {{- if .Values.hubble.tls.enabled }} @@ -158,7 +158,7 @@ spec: - name: host-os-release hostPath: path: /etc/os-release - type: FileOrCreate + type: FileOrCreate - name: tmp emptyDir: {} {{- if .Values.hubble.tls.enabled }} diff --git a/go.mod b/go.mod index c48be0d33b..286836cbc9 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module github.com/microsoft/retina go 1.25.0 require ( - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/google/uuid v1.6.0 - github.com/prometheus/client_golang v1.23.0 - github.com/spf13/cobra v1.10.1 + github.com/prometheus/client_golang v1.23.2 + github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.27.1 - k8s.io/client-go v0.32.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0 - sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 + k8s.io/client-go v0.35.3 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0 + sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 ) retract ( @@ -21,7 +21,6 @@ retract ( require ( cel.dev/expr v0.25.1 // indirect code.cloudfoundry.org/clock v1.0.0 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0 // indirect @@ -29,7 +28,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.29 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.24 // indirect @@ -37,7 +36,7 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect - github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + github.com/BurntSushi/toml v1.6.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect @@ -46,18 +45,18 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect github.com/aws/smithy-go v1.24.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 @@ -65,48 +64,39 @@ require ( github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a // indirect github.com/cilium/lumberjack/v2 v2.4.1 // indirect - github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect + github.com/cilium/stream v0.0.1 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect - github.com/containerd/containerd v1.7.29 // indirect + github.com/containerd/containerd v1.7.30 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect - github.com/containernetworking/cni v1.2.3 // indirect + github.com/containernetworking/cni v1.3.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cyphar/filepath-securejoin v0.5.1 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v26.0.0+incompatible // indirect - github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v28.5.2+incompatible // indirect - github.com/docker/docker-credential-helpers v0.8.1 // indirect - github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/emicklei/go-restful/v3 v3.12.2 // indirect - github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect github.com/evanphx/json-patch v5.9.11+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/color v1.18.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/fatih/color v1.19.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/errors v0.22.1 // indirect - github.com/go-openapi/jsonpointer v0.21.1 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.22.0 // indirect - github.com/go-openapi/runtime v0.28.0 // indirect - github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-openapi/strfmt v0.23.0 // indirect - github.com/go-openapi/swag v0.23.1 // indirect - github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-openapi/analysis v0.24.1 // indirect + github.com/go-openapi/errors v0.22.6 // indirect + github.com/go-openapi/jsonpointer v0.22.4 // indirect + github.com/go-openapi/jsonreference v0.21.4 // indirect + github.com/go-openapi/loads v0.23.2 // indirect + github.com/go-openapi/runtime v0.29.2 // indirect + github.com/go-openapi/spec v0.22.3 // indirect + github.com/go-openapi/strfmt v0.25.0 // indirect + github.com/go-openapi/swag v0.25.4 // indirect + github.com/go-openapi/validate v0.25.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect @@ -114,129 +104,112 @@ require ( github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/gnostic-models v0.7.0 // indirect github.com/google/gops v0.3.28 // indirect - github.com/google/renameio/v2 v2.0.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/google/renameio/v2 v2.0.2 // indirect + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/josharian/native v1.1.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/lib/pq v1.10.9 // indirect + github.com/lib/pq v1.11.2 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/mackerelio/go-osstat v0.2.5 // indirect - github.com/mailru/easyjson v0.9.0 // indirect + github.com/mackerelio/go-osstat v0.2.6 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mdlayher/socket v0.5.1 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/mdlayher/socket v0.6.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.5.0 // indirect - github.com/moby/term v0.5.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/peterbourgon/diskv v2.0.2-0.20180312054125-0646ccaebea1+incompatible // indirect - github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect + github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/procfs v0.16.1 // indirect - github.com/rubenv/sql-migrate v1.7.1 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/rubenv/sql-migrate v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.7.0 // indirect - github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sasha-s/go-deadlock v0.3.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect - github.com/spiffe/spire-api-sdk v1.12.0 // indirect + github.com/spiffe/spire-api-sdk v1.14.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect github.com/vishvananda/netns v0.0.5 // 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 github.com/xlab/treeprint v1.2.0 // indirect - go.etcd.io/etcd/api/v3 v3.5.21 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect - go.etcd.io/etcd/client/v3 v3.5.21 // indirect - go.mongodb.org/mongo-driver v1.14.0 // indirect + go.etcd.io/etcd/api/v3 v3.6.7 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.7 // indirect + go.etcd.io/etcd/client/v3 v3.6.7 // indirect + go.mongodb.org/mongo-driver v1.17.6 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.49.0 // indirect - golang.org/x/mod v0.33.0 - golang.org/x/text v0.35.0 // indirect + golang.org/x/crypto v0.50.0 // indirect + golang.org/x/mod v0.35.0 + golang.org/x/text v0.36.0 // indirect golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.42.0 // indirect + golang.org/x/tools v0.44.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/apiserver v0.32.3 // indirect - k8s.io/component-base v0.32.3 // indirect - oras.land/oras-go v1.2.5 // indirect - sigs.k8s.io/kustomize/api v0.18.0 // indirect - sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect + k8s.io/apiserver v0.35.3 // indirect + k8s.io/component-base v0.35.3 // indirect + sigs.k8s.io/kustomize/api v0.20.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect ) require ( github.com/go-chi/chi v4.1.2+incompatible - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.3 github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.7.0 - github.com/google/gofuzz v1.2.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/spf13/pflag v1.0.9 + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.52.0 // indirect - golang.org/x/oauth2 v0.34.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/oauth2 v0.35.0 // indirect golang.org/x/sync v0.20.0 - golang.org/x/sys v0.42.0 - golang.org/x/term v0.41.0 // indirect + golang.org/x/sys v0.43.0 + golang.org/x/term v0.42.0 // indirect google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.32.4 - k8s.io/apimachinery v0.32.4 + k8s.io/api v0.35.3 + k8s.io/apimachinery v0.35.3 k8s.io/klog/v2 v2.140.0 // indirect - k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/yaml v1.6.0 ) @@ -252,18 +225,17 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 github.com/Microsoft/hcsshim v0.14.1 - github.com/Sytten/logrus-zap-hook v0.1.0 github.com/aws/aws-sdk-go-v2 v1.41.5 - github.com/aws/aws-sdk-go-v2/config v1.31.6 - github.com/aws/aws-sdk-go-v2/credentials v1.19.7 + github.com/aws/aws-sdk-go-v2/config v1.32.14 + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 - github.com/cilium/cilium v1.18.0-pre.1 - github.com/cilium/ebpf v0.18.0 - github.com/cilium/hive v0.0.0-20250328192914-7f3c86c9c25e - github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb + github.com/cilium/cilium v1.19.3 + github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9 + github.com/cilium/hive v0.0.0-20260108104938-97756f6ff54c + github.com/cilium/proxy v0.0.0-20250623105955-2136f59a4ea1 github.com/cilium/workerpool v1.3.0 github.com/florianl/go-tc v0.4.8 github.com/go-logr/zapr v1.3.0 @@ -272,66 +244,72 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 - github.com/mdlayher/netlink v1.10.0 + github.com/mdlayher/netlink v1.11.0 github.com/microsoft/ApplicationInsights-Go v0.4.4 - github.com/mitchellh/mapstructure v1.5.0 + github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c github.com/onsi/ginkgo/v2 v2.28.1 github.com/onsi/gomega v1.39.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.67.5 github.com/safchain/ethtool v0.7.0 - github.com/sirupsen/logrus v1.9.3 - github.com/spf13/viper v1.20.1 - github.com/vishvananda/netlink v1.3.1 + github.com/spf13/viper v1.21.0 + github.com/vishvananda/netlink v1.3.2-0.20260109214200-c6faf428e8f8 go.opentelemetry.io/otel v1.43.0 go.opentelemetry.io/otel/metric v1.43.0 go.opentelemetry.io/otel/trace v1.43.0 go.uber.org/mock v0.6.0 - golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 + go.uber.org/zap/exp v0.3.0 + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f google.golang.org/grpc v1.80.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 - helm.sh/helm/v3 v3.17.4 - k8s.io/apiextensions-apiserver v0.32.3 - k8s.io/cli-runtime v0.32.3 - k8s.io/kubectl v0.32.3 - k8s.io/metrics v0.32.3 + helm.sh/helm/v3 v3.20.2 + k8s.io/apiextensions-apiserver v0.35.3 + k8s.io/cli-runtime v0.35.3 + k8s.io/kubectl v0.35.3 + k8s.io/metrics v0.35.3 k8s.io/perf-tests/network/benchmarks/netperf v0.0.0-00010101000000-000000000000 - sigs.k8s.io/controller-runtime v0.20.4 + sigs.k8s.io/controller-runtime v0.23.3 ) require ( github.com/antlr4-go/antlr/v4 v4.13.1 // indirect - github.com/cilium/statedb v0.3.7 + github.com/cilium/statedb v0.5.6 github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/platforms v1.0.0-rc.1 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect - github.com/google/cel-go v0.24.1 // indirect + github.com/google/cel-go v0.26.1 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect ) require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect - cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.15.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect + cloud.google.com/go v0.121.6 // indirect + cloud.google.com/go/auth v0.18.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect - cloud.google.com/go/iam v1.2.2 // indirect - cloud.google.com/go/kms v1.20.1 // indirect - cloud.google.com/go/longrunning v0.6.2 // indirect - cloud.google.com/go/monitoring v1.21.2 // indirect - cloud.google.com/go/storage v1.49.0 // indirect + cloud.google.com/go/iam v1.5.3 // indirect + cloud.google.com/go/kms v1.23.2 // indirect + cloud.google.com/go/longrunning v0.7.0 // indirect + cloud.google.com/go/monitoring v1.24.3 // indirect + cloud.google.com/go/storage v1.57.1 // indirect code.gitea.io/sdk/gitea v0.18.0 // indirect - dario.cat/mergo v1.0.1 // indirect - github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect + codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect + dario.cat/mergo v1.0.2 // indirect + dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect + dev.gaijin.team/go/golib v0.6.0 // indirect + github.com/4meepo/tagalign v1.4.3 // indirect + github.com/Abirdcfly/dupword v0.1.7 // indirect + github.com/AdminBenni/iota-mixing v1.0.0 // indirect github.com/AlekSi/pointer v1.2.0 // indirect - github.com/Antonboom/errname v1.0.0 // indirect - github.com/Antonboom/nilnil v1.0.1 // indirect - github.com/Antonboom/testifylint v1.5.2 // indirect + github.com/AlwxSin/noinlineerr v1.0.5 // indirect + github.com/Antonboom/errname v1.1.1 // indirect + github.com/Antonboom/nilnil v1.1.1 // indirect + github.com/Antonboom/testifylint v1.6.4 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0 // indirect @@ -343,46 +321,50 @@ require ( github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect github.com/Azure/msi-dataplane v0.4.3 // indirect - github.com/Crocmagnon/fatcontext v0.7.1 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect + github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 // indirect + github.com/MirrexOne/unqueryvet v1.5.4 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/ProtonMail/go-crypto v1.1.3 // indirect + github.com/ProtonMail/go-crypto v1.4.1 // indirect + github.com/alecthomas/chroma/v2 v2.23.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alessio/shellescape v1.4.1 // indirect - github.com/alexkohler/nakedret/v2 v2.0.5 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alexkohler/nakedret/v2 v2.0.6 // indirect + github.com/alexkohler/prealloc v1.1.0 // indirect + github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/alingse/nilnesserr v0.1.2 // indirect - github.com/anchore/bubbly v0.0.0-20230518153401-87b6af8ccf22 // indirect - github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a // indirect - github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb // indirect - github.com/anchore/quill v0.4.1 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/alingse/nilnesserr v0.2.0 // indirect + github.com/anchore/bubbly v0.0.0-20250717181826-8a411f9d8cbf // indirect + github.com/anchore/go-logger v0.0.0-20251106021608-a5b0513fa9a9 // indirect + github.com/anchore/go-macholibre v0.0.0-20250826193721-3cd206ca93aa // indirect + github.com/anchore/quill v0.7.1 // indirect + github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect + github.com/ashanbrown/makezero/v2 v2.1.0 // indirect github.com/atc0005/go-teams-notify/v2 v2.10.0 // indirect - github.com/aws/aws-sdk-go v1.53.0 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 // indirect - github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f // indirect + github.com/aws/aws-sdk-go v1.55.8 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.49.1 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect - github.com/blacktop/go-dwarf v1.0.9 // indirect - github.com/blacktop/go-macho v1.1.162 // indirect + github.com/blacktop/go-dwarf v1.0.14 // indirect + github.com/blacktop/go-macho v1.1.263 // indirect github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect + github.com/blang/semver v3.5.1+incompatible // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bluesky-social/indigo v0.0.0-20240411170459-440932307e0d // indirect - github.com/bombsimon/wsl/v4 v4.5.0 // indirect - github.com/breml/bidichk v0.3.2 // indirect - github.com/breml/errchkjson v0.4.0 // indirect - github.com/buger/jsonparser v1.1.2 // indirect - github.com/butuzov/ireturn v0.3.1 // indirect + github.com/bombsimon/wsl/v4 v4.7.0 // indirect + github.com/bombsimon/wsl/v5 v5.6.0 // indirect + github.com/breml/bidichk v0.3.3 // indirect + github.com/breml/errchkjson v0.4.1 // indirect + github.com/buger/jsonparser v1.1.1 // indirect + github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/caarlos0/ctrlc v1.2.0 // indirect github.com/caarlos0/env/v11 v11.0.1 // indirect @@ -391,46 +373,80 @@ require ( github.com/caarlos0/go-version v0.1.1 // indirect github.com/caarlos0/log v0.4.4 // indirect github.com/carlmjohnson/versioninfo v0.22.5 // indirect - github.com/catenacyber/perfsprint v0.8.2 // indirect + github.com/catenacyber/perfsprint v0.10.1 // indirect github.com/cavaliergopher/cpio v1.0.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/charithe/durationcheck v0.0.10 // indirect - github.com/charmbracelet/bubbletea v0.22.1 // indirect - github.com/charmbracelet/lipgloss v0.10.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/charithe/durationcheck v0.0.11 // indirect + github.com/charmbracelet/bubbletea v1.3.10 // indirect + github.com/charmbracelet/colorprofile v0.4.1 // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.11.3 // indirect + github.com/charmbracelet/x/cellbuf v0.0.14 // indirect github.com/charmbracelet/x/exp/ordered v0.0.0-20231010190216-1cb11efc897d // indirect - github.com/chavacava/garif v0.1.0 // indirect + github.com/charmbracelet/x/term v0.2.2 // indirect github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect - github.com/ckaznocha/intrange v0.3.0 // indirect - github.com/cloudflare/circl v1.6.1 // indirect - github.com/containerd/console v1.0.4 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/ckaznocha/intrange v0.3.1 // indirect + github.com/clipperhouse/displaywidth v0.6.2 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.3.0 // indirect + github.com/cloudflare/cfssl v1.6.5 // indirect + github.com/cloudflare/circl v1.6.3 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.18.1 // indirect + github.com/coreos/go-oidc/v3 v3.17.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect + github.com/creack/pty v1.1.24 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.5 // indirect + github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect + github.com/daixiang0/gci v0.13.7 // indirect + github.com/dave/dst v0.27.3 // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect github.com/dghubble/go-twitter v0.0.0-20211115160449-93a8679adecb // indirect github.com/dghubble/oauth1 v0.7.3 // indirect github.com/dghubble/sling v1.4.0 // indirect + github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect + github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect + github.com/docker/cli v29.2.1+incompatible // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker v28.5.2+incompatible // indirect + github.com/docker/docker-credential-helpers v0.9.3 // indirect + github.com/docker/go-connections v0.6.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.5 // indirect - github.com/fxamacker/cbor/v2 v2.8.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/firefart/nonamedreturns v1.0.6 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect - github.com/ghostiam/protogetter v0.3.9 // indirect + github.com/gabriel-vasile/mimetype v1.4.13 // indirect + github.com/ghostiam/protogetter v0.3.20 // indirect github.com/github/smimesign v0.2.0 // indirect - github.com/go-critic/go-critic v0.12.0 // indirect + github.com/go-critic/go-critic v0.14.3 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.0 // indirect - github.com/go-git/go-git/v5 v5.13.0 // indirect + github.com/go-git/go-billy/v5 v5.8.0 // indirect + github.com/go-git/go-git/v5 v5.17.1 // indirect + github.com/go-openapi/swag/cmdutils v0.25.4 // indirect + github.com/go-openapi/swag/conv v0.25.4 // indirect + github.com/go-openapi/swag/fileutils v0.25.4 // indirect + github.com/go-openapi/swag/jsonname v0.25.4 // indirect + github.com/go-openapi/swag/jsonutils v0.25.4 // indirect + github.com/go-openapi/swag/loading v0.25.4 // indirect + github.com/go-openapi/swag/mangling v0.25.4 // indirect + github.com/go-openapi/swag/netutils v0.25.4 // indirect + github.com/go-openapi/swag/stringutils v0.25.4 // indirect + github.com/go-openapi/swag/typeutils v0.25.4 // indirect + github.com/go-openapi/swag/yamlutils v0.25.4 // indirect github.com/go-restruct/restruct v1.2.0-alpha // indirect github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect @@ -440,30 +456,35 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobuffalo/flect v1.0.3 // indirect - github.com/gofrs/flock v0.12.1 // indirect + github.com/godoc-lint/godoc-lint v0.11.2 // indirect + github.com/gofrs/flock v0.13.0 // indirect + github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect - github.com/golangci/go-printf-func-name v0.1.0 // indirect + github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint v1.64.7 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/golangci-lint/v2 v2.11.4 // indirect + github.com/golangci/golines v0.15.0 // indirect + github.com/golangci/misspell v0.8.0 // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect - github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect - github.com/google/go-containerregistry v0.20.1 // indirect + github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect + github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect + github.com/google/certificate-transparency-go v1.3.2 // indirect + github.com/google/go-containerregistry v0.20.7 // indirect github.com/google/go-github/v62 v62.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/ko v0.15.4 // indirect github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect - github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a // indirect + github.com/google/rpmpack v0.7.1 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect github.com/google/wire v0.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect - github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.9 // indirect + github.com/googleapis/gax-go/v2 v2.16.0 // indirect + github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/goreleaser/chglog v0.6.1 // indirect github.com/goreleaser/fileglob v1.3.0 // indirect github.com/goreleaser/goreleaser v1.26.2 // indirect @@ -471,11 +492,16 @@ require ( github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/gostaticanalysis/nilerr v0.1.2 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/in-toto/attestation v1.1.2 // indirect + github.com/in-toto/in-toto-golang v0.9.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-block-format v0.2.0 // indirect @@ -491,48 +517,53 @@ require ( github.com/ipfs/go-metrics-interface v0.0.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jbenet/goprocess v0.1.4 // indirect - github.com/jgautheron/goconst v1.7.1 // indirect + github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect + github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect github.com/julz/importas v0.2.0 // indirect - github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/kisielk/errcheck v1.9.0 // indirect + github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect + github.com/kevinburke/ssh_config v1.4.0 // indirect + github.com/kisielk/errcheck v1.10.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/pgzip v1.2.6 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.10 // indirect + github.com/kulti/thelper v0.7.1 // indirect + github.com/kunwardeep/paralleltest v1.0.15 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.2 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect - github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.2 // indirect + github.com/ldez/exptostd v0.4.5 // indirect + github.com/ldez/gomoddirectives v0.8.0 // indirect + github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/structtags v0.6.1 // indirect + github.com/ldez/tagliatelle v0.7.2 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect - github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/macabu/inamedparam v0.1.3 // indirect - github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.1 // indirect + github.com/lucasb-eyer/go-colorful v1.3.0 // indirect + github.com/macabu/inamedparam v0.2.0 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect + github.com/manuelarte/funcorder v0.5.0 // indirect + github.com/maratori/testableexamples v1.0.1 // indirect + github.com/maratori/testpackage v1.1.2 // indirect github.com/matoous/godox v1.1.0 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect github.com/mattn/go-mastodon v0.0.8 // indirect - github.com/mgechev/revive v1.7.0 // indirect + github.com/mgechev/revive v1.15.0 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/moby/sys/atomicwriter v0.1.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/moby/api v1.54.0 // indirect + github.com/moby/moby/client v0.3.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/mr-tron/base58 v1.2.0 // indirect - github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/mango v0.1.0 // indirect github.com/muesli/mango-cobra v1.2.0 // indirect github.com/muesli/mango-pflag v0.1.0 // indirect - github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/roff v0.1.0 // indirect - github.com/muesli/termenv v0.15.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect @@ -541,125 +572,136 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.19.1 // indirect + github.com/nunnatsa/ginkgolinter v0.23.0 // indirect github.com/nxadm/tail v1.4.11 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect + github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect - github.com/polyfloyd/go-errorlint v1.7.1 // indirect - github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect - github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/quasilyte/go-ruleguard v0.4.5 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.23 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/raeperd/recvcheck v0.2.0 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 // indirect - github.com/redis/go-redis/v9 v9.7.3 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/ryancurrah/gomodguard v1.3.5 // indirect - github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect + github.com/ryancurrah/gomodguard v1.4.1 // indirect + github.com/ryanrolds/sqlclosecheck v0.6.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/sassoftware/relic v7.2.1+incompatible // indirect github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e // indirect - github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect - github.com/securego/gosec/v2 v2.22.2 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.10.0 // indirect + github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/sigstore/cosign/v2 v2.2.4 // indirect - github.com/sigstore/rekor v1.3.6 // indirect - github.com/sigstore/sigstore v1.8.3 // indirect + github.com/shibumi/go-pathspec v1.3.0 // indirect + github.com/sigstore/cosign/v2 v2.6.2 // indirect + github.com/sigstore/protobuf-specs v0.5.0 // indirect + github.com/sigstore/rekor v1.5.0 // indirect + github.com/sigstore/rekor-tiles/v2 v2.0.1 // indirect + github.com/sigstore/sigstore v1.10.4 // indirect + github.com/sigstore/sigstore-go v1.1.4 // indirect + github.com/sigstore/timestamp-authority/v2 v2.0.3 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sivchari/tenv v1.12.1 // indirect - github.com/skeema/knownhosts v1.3.0 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect github.com/slack-go/slack v0.13.0 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.5.1 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect + github.com/stbenjam/no-sprintf-host-port v0.3.1 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/tdakkota/asciicheck v0.4.1 // indirect - github.com/tetafro/godot v1.5.0 // indirect - github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect - github.com/timonwong/loggercheck v0.10.1 // indirect - github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect - github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect + github.com/tetafro/godot v1.5.4 // indirect + github.com/theupdateframework/go-tuf v0.7.0 // indirect + github.com/theupdateframework/go-tuf/v2 v2.3.0 // indirect + github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect + github.com/timonwong/loggercheck v0.11.0 // indirect + github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect - github.com/ulikunitz/xz v0.5.12 // indirect + github.com/transparency-dev/formats v0.0.0-20251017110053-404c0d5b696c // indirect + github.com/transparency-dev/merkle v0.0.2 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect - github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect - github.com/vbatts/tar-split v0.11.5 // indirect + github.com/uudashr/gocognit v1.2.1 // indirect + github.com/uudashr/iface v1.4.1 // indirect + github.com/vbatts/tar-split v0.12.2 // indirect github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 // indirect - github.com/wagoodman/go-progress v0.0.0-20220614130704-4b1c25a33c7c // indirect + github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 // indirect github.com/whyrusleeping/cbor-gen v0.1.1-0.20240311221002-68b9f235c302 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/go-gitlab v0.105.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xen0n/gosmopolitan v1.2.2 // indirect + github.com/xen0n/gosmopolitan v1.3.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect - go-simpler.org/musttag v0.13.0 // indirect - go-simpler.org/sloglint v0.9.0 // indirect + go-simpler.org/musttag v0.14.0 // indirect + go-simpler.org/sloglint v0.11.1 // indirect + go.augendre.info/arangolint v0.4.0 // indirect + go.augendre.info/fatcontext v0.9.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.40.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.65.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.16.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.yaml.in/yaml/v2 v2.4.3 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - gocloud.dev v0.37.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/tools/go/expect v0.1.1-deprecated // indirect - golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/api v0.223.0 // indirect + gocloud.dev v0.40.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect + golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect + google.golang.org/api v0.260.0 // indirect + google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/mail.v2 v2.3.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - honnef.co/go/tools v0.6.1 // indirect + honnef.co/go/tools v0.7.0 // indirect + k8s.io/code-generator v0.35.3 // indirect + k8s.io/component-helpers v0.35.3 // indirect + k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect lukechampine.com/blake3 v1.2.1 // indirect - mvdan.cc/gofumpt v0.7.0 // indirect - mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect + mvdan.cc/gofumpt v0.9.2 // indirect + mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect + oras.land/oras-go/v2 v2.6.0 // indirect sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5 // indirect - sigs.k8s.io/controller-tools v0.16.5 // indirect - sigs.k8s.io/gateway-api v1.2.1-0.20250319040149-e8b8afabf889 // indirect + sigs.k8s.io/controller-tools v0.19.0 // indirect + sigs.k8s.io/gateway-api v1.4.0-rc.2 // indirect sigs.k8s.io/kind v0.23.0 // indirect - sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0 // indirect - sigs.k8s.io/mcs-api/controllers v0.0.0-20250224121229-6c631f4730d0 // indirect + sigs.k8s.io/mcs-api v0.3.1-0.20260224125735-0f775a3eff97 // indirect + sigs.k8s.io/mcs-api/controllers v0.0.0-20260403094305-4b9911b73f14 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - software.sslmate.com/src/go-pkcs12 v0.4.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect + software.sslmate.com/src/go-pkcs12 v0.7.0 // indirect ) -replace github.com/vishvananda/netns => github.com/inspektor-gadget/netns v0.0.5-0.20230524185006-155d84c555d6 - -replace k8s.io/perf-tests/network/benchmarks/netperf => github.com/Azure/perf-tests/network/benchmarks/netperf v0.0.0-20241008140716-395a79947d2c - -replace go.universe.tf/metallb => github.com/cilium/metallb v0.1.1-0.20220829170633-5d7dfb1129f7 - tool ( github.com/cilium/ebpf/cmd/bpf2go - github.com/golangci/golangci-lint/cmd/golangci-lint + github.com/golangci/golangci-lint/v2/cmd/golangci-lint github.com/goreleaser/goreleaser github.com/onsi/ginkgo go.uber.org/mock/mockgen @@ -667,3 +709,5 @@ tool ( sigs.k8s.io/controller-runtime/tools/setup-envtest sigs.k8s.io/controller-tools/cmd/controller-gen ) + +replace k8s.io/perf-tests/network/benchmarks/netperf => github.com/Azure/perf-tests/network/benchmarks/netperf v0.0.0-20241008140716-395a79947d2c diff --git a/go.sum b/go.sum index 6d4fd3dcd0..949668bc57 100644 --- a/go.sum +++ b/go.sum @@ -5,52 +5,65 @@ cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= -cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= -cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= -cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= -cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= +cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c= +cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI= +cloud.google.com/go/auth v0.18.0 h1:wnqy5hrv7p3k7cShwAU/Br3nzod7fxoqG+k0VZ+/Pk0= +cloud.google.com/go/auth v0.18.0/go.mod h1:wwkPM1AgE1f2u6dG443MiWoD8C3BtOywNsUMcUTVDRo= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= -cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= -cloud.google.com/go/kms v1.20.1 h1:og29Wv59uf2FVaZlesaiDAqHFzHaoUyHI3HYp9VUHVg= -cloud.google.com/go/kms v1.20.1/go.mod h1:LywpNiVCvzYNJWS9JUcGJSVTNSwPwi0vBAotzDqn2nc= -cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= -cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= -cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= -cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= -cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= -cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= -cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= -cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= -cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= -cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= +cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= +cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= +cloud.google.com/go/kms v1.23.2 h1:4IYDQL5hG4L+HzJBhzejUySoUOheh3Lk5YT4PCyyW6k= +cloud.google.com/go/kms v1.23.2/go.mod h1:rZ5kK0I7Kn9W4erhYVoIRPtpizjunlrfU4fUkumUp8g= +cloud.google.com/go/logging v1.13.1 h1:O7LvmO0kGLaHY/gq8cV7T0dyp6zJhYAOtZPX4TF3QtY= +cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= +cloud.google.com/go/longrunning v0.7.0 h1:FV0+SYF1RIj59gyoWDRi45GiYUMM3K1qO51qoboQT1E= +cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY= +cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= +cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= +cloud.google.com/go/storage v1.57.1 h1:gzao6odNJ7dR3XXYvAgPK+Iw4fVPPznEPPyNjbaVkq8= +cloud.google.com/go/storage v1.57.1/go.mod h1:329cwlpzALLgJuu8beyJ/uvQznDHpa2U5lGjWednkzg= +cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= +cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= code.cloudfoundry.org/clock v1.0.0 h1:kFXWQM4bxYvdBw2X8BbBeXwQNgfoWv1vqAk2ZZyBN2o= code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= code.gitea.io/sdk/gitea v0.18.0 h1:+zZrwVmujIrgobt6wVBWCqITz6bn1aBjnCUHmpZrerI= code.gitea.io/sdk/gitea v0.18.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI= -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +codeberg.org/polyfloyd/go-errorlint v1.9.0 h1:VkdEEmA1VBpH6ecQoMR4LdphVI3fA4RrCh2an7YmodI= +codeberg.org/polyfloyd/go-errorlint v1.9.0/go.mod h1:GPRRu2LzVijNn4YkrZYJfatQIdS+TrcK8rL5Xs24qw8= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= +dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= +dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= -github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= +github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= +github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= +github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ= +github.com/Abirdcfly/dupword v0.1.7/go.mod h1:K0DkBeOebJ4VyOICFdppB23Q0YMOgVafM0zYW0n9lF4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM= +github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo= +github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY= github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= -github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= -github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= -github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= -github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= -github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= -github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= +github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= +github.com/Antonboom/errname v1.1.1 h1:bllB7mlIbTVzO9jmSWVWLjxTEbGBVQ1Ff/ClQgtPw9Q= +github.com/Antonboom/errname v1.1.1/go.mod h1:gjhe24xoxXp0ScLtHzjiXp0Exi1RFLKJb0bVBtWKCWQ= +github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksufQ= +github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II= +github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= +github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiXP99Ss5D+UJ80EL2mzPgNRhk= github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= @@ -109,14 +122,16 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v2 v2.0.0 h1:+vh02EiRx2UmL9NDoA36U18Bgwl9luxs6ia0GAI9Rzg= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v2 v2.0.0/go.mod h1:iKOtU3WyuNvNc4L1Z4IxHaoO0dGq5tg+uhLix/KRmzE= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0 h1:E4MgwLBGeVB5f2MdcIVD3ELVAWpr+WD6MUe1i+tM/PA= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0/go.mod h1:Y2b/1clN4zsAoUd/pgNAQHjLDnTis/6ROkUfyob6psM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S6wk65vfC6m3FIxJ+i5QDyN9JWwXI8Hb0Img10hU= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 h1:FwladfywkNirM+FZYLBR2kBz5C8Tg0fw5w5Y7meRXWI= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2/go.mod h1:vv5Ad0RrIoT1lJFdWBZwt4mB1+j+V8DUroixmKDTCdk= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 h1:jWQK1GI+LeGGUKBADtcH2rRqPxYB1Ljwms5gFA2LqrM= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4/go.mod h1:8mwH4klAm9DUgR2EEHyEEAQlRDvLPyg5fQry3y+cDew= +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/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= @@ -151,26 +166,22 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mo github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= -github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= +github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= +github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 h1:lhhYARPUu3LmHysQ/igznQphfzynnqI3D75oUyw1HXk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0/go.mod h1:l9rva3ApbBpEJxSNYnwT9N4CDLrWgtq3u8736C5hyJw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0 h1:xfK3bbi6F2RDtaZFtUdKO3osOBIhNb+xTs8lFW6yx9o= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 h1:s0WlVbf9qpvkh1c/uDAPElam0WrL7fHRIidgZJ7UqZI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -186,88 +197,89 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= +github.com/MirrexOne/unqueryvet v1.5.4 h1:38QOxShO7JmMWT+eCdDMbcUgGCOeJphVkzzRgyLJgsQ= +github.com/MirrexOne/unqueryvet v1.5.4/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU= 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/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= -github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= -github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM= +github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= github.com/ProtonMail/gopenpgp/v2 v2.7.1 h1:Awsg7MPc2gD3I7IFac2qE3Gdls0lZW8SzrFZ3k1oz0s= github.com/ProtonMail/gopenpgp/v2 v2.7.1/go.mod h1:/BU5gfAVwqyd8EfC3Eu7zmuhwYQpKs+cGD8M//iiaxs= -github.com/Sytten/logrus-zap-hook v0.1.0 h1:GPsDlO0b+rvfb6WohFNreI3Fe2I6MDyv1afoYPE2Kzk= -github.com/Sytten/logrus-zap-hook v0.1.0/go.mod h1:J0ktevklw/xJNpI2FzfTdJssk4P0vq3K2qzwihJ2gWU= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= +github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= -github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= -github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= -github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= +github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= +github.com/alexkohler/prealloc v1.1.0 h1:cKGRBqlXw5iyQGLYhrXrDlcHxugXpTq4tQ5c91wkf8M= +github.com/alexkohler/prealloc v1.1.0/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= +github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= +github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= -github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/anchore/bubbly v0.0.0-20230518153401-87b6af8ccf22 h1:5NFK6VGgqBUOAX2SYyzFYvNdOiYDxzim8jga386FlZY= -github.com/anchore/bubbly v0.0.0-20230518153401-87b6af8ccf22/go.mod h1:Kv+Mm9CdtnV8iem48iEPIwy7/N4Wmk0hpxYNH5gTwKQ= -github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw= -github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg= -github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU= -github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb/go.mod h1:DmTY2Mfcv38hsHbG78xMiTDdxFtkHpgYNVDPsF2TgHk= -github.com/anchore/quill v0.4.1 h1:mffDnvnER3ZgPjN5hexc3nr/4Y1dtKdDB6td5K8uInk= -github.com/anchore/quill v0.4.1/go.mod h1:t6hOPYDohN8wn2SRWQdNkJBkhmK8s3gzuHzzgcEvzQU= +github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= +github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/anchore/bubbly v0.0.0-20250717181826-8a411f9d8cbf h1:UY7SQkfVVaeGUpPZrJxqmTc8M0ZSWc5ChiKF6I6aL3I= +github.com/anchore/bubbly v0.0.0-20250717181826-8a411f9d8cbf/go.mod h1:w8Br1ZKk1Nk82YRSh10pcD7LO7avPyFmNnaY1TRPgs0= +github.com/anchore/go-logger v0.0.0-20251106021608-a5b0513fa9a9 h1:k+D5tVys8MC+CxfzXIOGm3bZ0FEkmn8udlKACPm4PPo= +github.com/anchore/go-logger v0.0.0-20251106021608-a5b0513fa9a9/go.mod h1:oFuE8YuTCM+spgMXhePGzk3asS94yO9biUfDzVTFqNw= +github.com/anchore/go-macholibre v0.0.0-20250826193721-3cd206ca93aa h1:KPEP8f3enFJeus3Wo51I+riVuCvlf4OEYl2B4IfycbQ= +github.com/anchore/go-macholibre v0.0.0-20250826193721-3cd206ca93aa/go.mod h1:7YJA6tAfRm4SzIF93b32pR4xnbf8g2nJIeQnp+2vzzI= +github.com/anchore/quill v0.7.1 h1:/K2Yvcjs3ipmP+hjxXmy+3IL/nZ0Tnj8S+OLZvtXRYI= +github.com/anchore/quill v0.7.1/go.mod h1:1ExdNP//bdjTRROE/MJg8MxLoDzIJH5HvsbMW4chpBo= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +github.com/ashanbrown/forbidigo/v2 v2.3.0 h1:OZZDOchCgsX5gvToVtEBoV2UWbFfI6RKQTir2UZzSxo= +github.com/ashanbrown/forbidigo/v2 v2.3.0/go.mod h1:5p6VmsG5/1xx3E785W9fouMxIOkvY2rRV9nMdWadd6c= +github.com/ashanbrown/makezero/v2 v2.1.0 h1:snuKYMbqosNokUKm+R6/+vOPs8yVAi46La7Ck6QYSaE= +github.com/ashanbrown/makezero/v2 v2.1.0/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY= github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyrdEQM3+c/nXhM= github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= -github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= -github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= +github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= -github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo= -github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ= -github.com/aws/aws-sdk-go-v2/credentials v1.19.7 h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.7/go.mod h1:qOZk8sPDrxhf+4Wf4oT2urYJrYt3RejHSzgAquYeppw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= +github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= +github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 h1:1hWFp+52Vq8Fevy/KUhbW/1MEApMz7uitCF/PQXRJpk= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1/go.mod h1:sIec8j802/rCkCKgZV678HFR0s7lhQUYXT77tIvlaa4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= -github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0 h1:rdPrcOZmqT2F+yzmKEImrx5XUs7Hpf4V9Rp6E8mhsxQ= -github.com/aws/aws-sdk-go-v2/service/ecr v1.28.0/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5 h1:452e/nFuqPvwPg+1OD2CG/v29R9MH8egJSJKh2Qduv8= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.5/go.mod h1:8pvvNAklmq+hKmqyvFoMRg0bwg9sdGOvdwximmKiKP0= +github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 h1:Bwzh202Aq7/MYnAjXA9VawCf6u+hjwMdoYmZ4HYsdf8= +github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1/go.mod h1:xZzWl9AXYa6zsLLH41HBFW8KRKJRIzlGmvSM0mVMIX4= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 h1:XJ/AEFYj9VFPJdF+VFi4SUPEDfz1akHwxxm07JfZJcs= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2/go.mod h1:JUBHdhvKbbKmhaHjLsKJAWnQL80T6nURmhB/LEprV+4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= @@ -276,55 +288,59 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3x github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= -github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= -github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= +github.com/aws/aws-sdk-go-v2/service/kms v1.49.1 h1:U0asSZ3ifpuIehDPkRI2rxHbmFUMplDA2VeR9Uogrmw= +github.com/aws/aws-sdk-go-v2/service/kms v1.49.1/go.mod h1:NZo9WJqQ0sxQ1Yqu1IwCHQFQunTms2MlVgejg16S1rY= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 h1:gd84Omyu9JLriJVCbGApcLzVR3XtmC4ZDPcAI6Ftvds= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f h1:Z0kS9pJDQgCg3u2lH6+CdYaFbyQtyukVTiUCG6re0E4= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240514230400-03fa26f5508f/go.mod h1:rAE739ssmE5O5fLuQ2y8uHdmOJaelE5I0Es3SxV0y1A= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 h1:6lMw4/QGLFPvbKQ0eri/9Oh3YX5Nm6BPrUlZR8yuJHg= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1/go.mod h1:EVJOSYOVeoD3VFFZ/dWCAzWJp5wZr9lTOCjW8ejAmO0= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= -github.com/blacktop/go-dwarf v1.0.9 h1:eT/L7gt0gllvvgnRXY0MFKjNB6+jtOY5DTm2ynVX2dY= -github.com/blacktop/go-dwarf v1.0.9/go.mod h1:4W2FKgSFYcZLDwnR7k+apv5i3nrau4NGl9N6VQ9DSTo= -github.com/blacktop/go-macho v1.1.162 h1:FjM3XAsJTAOGZ1eppRSX9ZBX3Bk11JMTC1amsZAOA5I= -github.com/blacktop/go-macho v1.1.162/go.mod h1:f2X4noFBob4G5bWUrzvPBKDVcFWZgDCM7rIn7ygTID0= +github.com/blacktop/go-dwarf v1.0.14 h1:OjmzfSgg/qAKckn2tWFebcgKgJ7HOqCj7bS+CiE1lrY= +github.com/blacktop/go-dwarf v1.0.14/go.mod h1:4W2FKgSFYcZLDwnR7k+apv5i3nrau4NGl9N6VQ9DSTo= +github.com/blacktop/go-macho v1.1.263 h1:wzcLdip1PD2UwOZ5liKijF4YlYbFFF7XdqjLp3VQ1d0= +github.com/blacktop/go-macho v1.1.263/go.mod h1:Hc5E2Lvt/U1VT+jOxr1O5l/LNFJeMYK4eAmDfazTiGc= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bluesky-social/indigo v0.0.0-20240411170459-440932307e0d h1:xxPhzCOpmOntzVe8S6tqsMdFgaB8B4NXSV54lG4B1qk= github.com/bluesky-social/indigo v0.0.0-20240411170459-440932307e0d/go.mod h1:ysMQ0a4RYWjgyvKrl5ME352oHA6QgK900g5sB9XXgPE= -github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A= -github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc= -github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= -github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= -github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= -github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= +github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= +github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v5 v5.6.0 h1:4z+/sBqC5vUmSp1O0mS+czxwH9+LKXtCWtHH9rZGQL8= +github.com/bombsimon/wsl/v5 v5.6.0/go.mod h1:Uqt2EfrMj2NV8UGoN1f1Y3m0NpUVCsUdrNCdet+8LvU= +github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= +github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= +github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= +github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk= -github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= -github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E= +github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= github.com/caarlos0/ctrlc v1.2.0 h1:AtbThhmbeYx1WW3WXdWrd94EHKi+0NPRGS4/4pzrjwk= @@ -345,81 +361,88 @@ github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 h1:BjkPE3785EwP github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5/go.mod h1:jtAfVaU/2cu1+wdSRPWE2c1N2qeAA3K4RH9pYgqwets= github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc= github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8= -github.com/catenacyber/perfsprint v0.8.2 h1:+o9zVmCSVa7M4MvabsWvESEhpsMkhfE7k0sHNGL95yw= -github.com/catenacyber/perfsprint v0.8.2/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= +github.com/catenacyber/perfsprint v0.10.1 h1:u7Riei30bk46XsG8nknMhKLXG9BcXz3+3tl/WpKm0PQ= +github.com/catenacyber/perfsprint v0.10.1/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc= github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= 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/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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= -github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/charmbracelet/bubbletea v0.22.1 h1:z66q0LWdJNOWEH9zadiAIXp2GN1AWrwNXU8obVY9X24= -github.com/charmbracelet/bubbletea v0.22.1/go.mod h1:8/7hVvbPN6ZZPkczLiB8YpLkLJ0n7DMho5Wvfd2X1C0= +github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1DidBcABctk= +github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4= +github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= +github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= +github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= +github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= github.com/charmbracelet/keygen v0.5.0 h1:XY0fsoYiCSM9axkrU+2ziE6u6YjJulo/b9Dghnw6MZc= github.com/charmbracelet/keygen v0.5.0/go.mod h1:DfvCgLHxZ9rJxdK0DGw3C/LkV4SgdGbnliHcObV3L+8= -github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s= -github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.11.3 h1:6DcVaqWI82BBVM/atTyq6yBoRLZFBsnoDoX9GCu2YOI= +github.com/charmbracelet/x/ansi v0.11.3/go.mod h1:yI7Zslym9tCJcedxz5+WBq+eUGMJT0bM06Fqy1/Y4dI= +github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4= +github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA= github.com/charmbracelet/x/exp/ordered v0.0.0-20231010190216-1cb11efc897d h1:+o+e/8hf7cG0SbAzEAm/usJ8qoZPgFXhudLjop+TM0g= github.com/charmbracelet/x/exp/ordered v0.0.0-20231010190216-1cb11efc897d/go.mod h1:aoG4bThKYIOnyB55r202eHqo6TkN7ZXV+cu4Do3eoBQ= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= -github.com/cilium/cilium v1.18.0-pre.1 h1:ZE+fNsr6QAVcKsvnO1WmMQF4Jo/aztYF1IGy77kb6i0= -github.com/cilium/cilium v1.18.0-pre.1/go.mod h1:xNfreZ/3t6IxynTSSqJRr8hZd2dhX0dns+ae/WDYwWk= +github.com/cilium/cilium v1.19.3 h1:foJrHPk45HwshOd8Qf/kptf9JxPfNySkIDKsetZa9+Y= +github.com/cilium/cilium v1.19.3/go.mod h1:cd4P5LHAg4hyyZexrM4D055t5JwyudeAcZ/Jub9VxJY= github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a h1:PRGN7B+72mj3OtLL2DM3F/9jp+ItgqgNS7mecgCmwsQ= github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a/go.mod h1:/7LC2GOgyXJ7maupZlaVIumYQiGPIgllSf6mA9sg6RU= github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk= -github.com/cilium/ebpf v0.18.0 h1:OsSwqS4y+gQHxaKgg2U/+Fev834kdnsQbtzRnbVC6Gs= -github.com/cilium/ebpf v0.18.0/go.mod h1:vmsAT73y4lW2b4peE+qcOqw6MxvWQdC+LiU5gd/xyo4= +github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9 h1:hQW7n5ePt/HDgeZLcyT3pFENyfa6vmaGU7M+tq2pa64= +github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9/go.mod h1:EGj6HpG/oejvbTAsMWwlA4UbMU7WBAgILd+9OSvcDTc= github.com/cilium/fake v0.7.0 h1:4EKBtTweQrJoD4q45qDGu8udulmYMo48Y0BhEbrB1jc= github.com/cilium/fake v0.7.0/go.mod h1:hA1YsEjgIs5Gdeq/DVrDWGuhLCoVok7THTvQaGDO5bc= -github.com/cilium/hive v0.0.0-20250328192914-7f3c86c9c25e h1:IbUxYFQHOMrcCjTlW2s4ir5tf4vqiYIMHCoV81DYIiQ= -github.com/cilium/hive v0.0.0-20250328192914-7f3c86c9c25e/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI= +github.com/cilium/hive v0.0.0-20260108104938-97756f6ff54c h1:mP/Z+oVplgbg3oV1lwsAC86NPLWioN/TqlmZ6+BI2I0= +github.com/cilium/hive v0.0.0-20260108104938-97756f6ff54c/go.mod h1:4/8FBMcTjVdkrNNWaB7t3QqaU4kZDJLJ1leKVP9GjEI= github.com/cilium/lumberjack/v2 v2.4.1 h1:tU92KFJmLQ4Uls5vTgok5b5RbfxpawRia7L14y2qDBs= github.com/cilium/lumberjack/v2 v2.4.1/go.mod h1:yfbtPGmg4i//5oEqzaMxDqSWqgfZFmMoV70Mc2k6v0A= -github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb h1:pV58137rRui6vUJT2HM2h0HcPfaAh+6BVH42oKXytH8= -github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb/go.mod h1:ZCm83Mm0aE17bm2vnYY3kS40VIT7ymoqZhNc8YXK1us= -github.com/cilium/statedb v0.3.7 h1:htzjXktKe37FNLGDQjM899G8BK4Pcp+GM1cFQVV3HGA= -github.com/cilium/statedb v0.3.7/go.mod h1:n2lNVxi8vz5Up1Y1rRD++aQP2izQA932fUwTkedKSV0= -github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 h1:f+CgYUy2YyZ2EX31QSqf3vwFiJJQSAMIQLn4d3QQYno= -github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744/go.mod h1:/e83AwqvNKpyg4n3C41qmnmj1x2G9DwzI+jb7GkF4lI= +github.com/cilium/proxy v0.0.0-20250623105955-2136f59a4ea1 h1:SOOtIfQmW/pF1iW1I4hVUx1pvgX7Xh2E8jHv+itBXQ0= +github.com/cilium/proxy v0.0.0-20250623105955-2136f59a4ea1/go.mod h1:Kwyyx+cC2H67Aj1sDuqBLvPn6TEmEJRPvULIrJ/kBRo= +github.com/cilium/statedb v0.5.6 h1:qid1eoMlWAYi02qMHL9Ewdhtd+FCoTF6nGUrcBB36to= +github.com/cilium/statedb v0.5.6/go.mod h1:utZbqAU8l3X/2zmbBwoYC2KuRTstuSqo+c4cw4jXsCM= +github.com/cilium/stream v0.0.1 h1:82zuM/WwkLiac2Jg5FrzPxZHvIBbxXTi4VY7M+EYLs0= +github.com/cilium/stream v0.0.1/go.mod h1:/e83AwqvNKpyg4n3C41qmnmj1x2G9DwzI+jb7GkF4lI= github.com/cilium/workerpool v1.3.0 h1:7BhHxoqNtpqtmce6MxZdgWODze4lYHbWkEUQ+3xEu8M= github.com/cilium/workerpool v1.3.0/go.mod h1:0evs6P39nORTphjRtTtHLXTyCPQUwelXCK4wBJmVP7g= -github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= -github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= +github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= +github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= +github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= +github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= +github.com/cloudflare/cfssl v1.6.5 h1:46zpNkm6dlNkMZH/wMW22ejih6gIaJbzL2du6vD7ZeI= +github.com/cloudflare/cfssl v1.6.5/go.mod h1:Bk1si7sq8h2+yVEDrFJiz3d7Aw+pfjjJSZVaD+Taky4= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= +github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= -github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE= -github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs= +github.com/containerd/containerd v1.7.30 h1:/2vezDpLDVGGmkUXmlNPLCCNKHJ5BbC5tJB5JNzQhqE= +github.com/containerd/containerd v1.7.30/go.mod h1:fek494vwJClULlTpExsmOyKCMUAbuVjlFsJQc4/j44M= 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= @@ -430,28 +453,39 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/containerd/stargz-snapshotter/estargz v0.18.1 h1:cy2/lpgBXDA3cDKSyEfNOFMA/c10O1axL69EU7iirO8= +github.com/containerd/stargz-snapshotter/estargz v0.18.1/go.mod h1:ALIEqa7B6oVDsrF37GkGN20SuvG/pIMm7FwP7ZmRb0Q= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= -github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= -github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= +github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo= +github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4= +github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc= +github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= +github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 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= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48= -github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= -github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= -github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q= +github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= +github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= +github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= +github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= +github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= +github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= +github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= +github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= +github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -468,49 +502,50 @@ github.com/dghubble/sling v1.4.0 h1:/n8MRosVTthvMbwlNZgLx579OGVjUOy3GNEv5BIqAWY= github.com/dghubble/sling v1.4.0/go.mod h1:0r40aNsU9EdDUVBNhfCstAtFgutjgJGYbO1oNzkMoM8= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= +github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQMIAH7uKg0lrtNSOdpYsRXlwk3QbaE= +github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= +github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 h1:lxmTCgmHE1GUYL7P0MlNa00M67axePTq+9nBSGddR8I= +github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7/go.mod h1:GvWntX9qiTlOud0WkQ6ewFm0LPy5JUR1Xo0Ngbd1w6Y= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/distribution/distribution/v3 v3.0.0-alpha.1 h1:jn7I1gvjOvmLztH1+1cLiUFud7aeJCIQcgzugtwjyJo= -github.com/distribution/distribution/v3 v3.0.0-alpha.1/go.mod h1:LCp4JZp1ZalYg0W/TN05jarCQu+h4w7xc7ZfQF4Y/cY= +github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM= +github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= 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/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= -github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.2.1+incompatible h1:n3Jt0QVCN65eiVBoUTZQM9mcQICCJt3akW4pKAbKdJg= +github.com/docker/cli v29.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 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/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= -github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= +github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= +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-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= 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/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug= -github.com/elazarl/goproxy v1.2.1/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= +github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= +github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/elliotchance/orderedmap/v2 v2.2.0 h1:7/2iwO98kYT4XkOjA9mBEIwvi4KpGB4cyHeOFOnj4Vk= github.com/elliotchance/orderedmap/v2 v2.2.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q= -github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= -github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= @@ -518,8 +553,10 @@ github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9O github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= -github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= @@ -531,20 +568,20 @@ github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSY github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= -github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= +github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/florianl/go-tc v0.4.8 h1:hgmakUX1Nm0Ba1I0ZkbUl9CH6HbRwqSiwipnpmYp3Es= github.com/florianl/go-tc v0.4.8/go.mod h1:B8GeOEnmrbOnxZtaCvsYJcgIzzmM8c/AIhtfCZsDj3Q= -github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= -github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= +github.com/foxcpp/go-mockdns v1.2.0 h1:omK3OrHRD1IWJz1FuFBCFquhXslXoF17OvBS6JPzZF0= +github.com/foxcpp/go-mockdns v1.2.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -552,17 +589,16 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= -github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= -github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= +github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/ghostiam/protogetter v0.3.20 h1:oW7OPFit2FxZOpmMRPP9FffU4uUpfeE/rEdE1f+MzD0= +github.com/ghostiam/protogetter v0.3.20/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= github.com/github/smimesign v0.2.0 h1:Hho4YcX5N1I9XNqhq0fNx0Sts8MhLonHd+HRXVGNjvk= github.com/github/smimesign v0.2.0/go.mod h1:iZiiwNT4HbtGRVqCQu7uJPEZCuEE5sfSSttcnePkDl4= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= @@ -575,10 +611,10 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= -github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= -github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOESA0pog= +github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-faker/faker/v4 v4.7.0 h1:VboC02cXHl/NuQh5lM2W8b87yp4iFXIu59x4w0RZi4E= @@ -587,19 +623,16 @@ github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= -github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM= +github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0= +github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= -github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= +github.com/go-git/go-git/v5 v5.17.1 h1:WnljyxIzSj9BRRUlnmAU35ohDsjRK0EKmL0evDqi5Jk= +github.com/go-git/go-git/v5 v5.17.1/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 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= @@ -607,41 +640,71 @@ 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-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= -github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= -github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= -github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= -github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= -github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= -github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= -github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= -github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= -github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= -github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= -github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= -github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= -github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +github.com/go-openapi/analysis v0.24.1 h1:Xp+7Yn/KOnVWYG8d+hPksOYnCYImE3TieBa7rBOesYM= +github.com/go-openapi/analysis v0.24.1/go.mod h1:dU+qxX7QGU1rl7IYhBC8bIfmWQdX4Buoea4TGtxXY84= +github.com/go-openapi/errors v0.22.6 h1:eDxcf89O8odEnohIXwEjY1IB4ph5vmbUsBMsFNwXWPo= +github.com/go-openapi/errors v0.22.6/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= +github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4= +github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80= +github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8= +github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4= +github.com/go-openapi/loads v0.23.2 h1:rJXAcP7g1+lWyBHC7iTY+WAF0rprtM+pm8Jxv1uQJp4= +github.com/go-openapi/loads v0.23.2/go.mod h1:IEVw1GfRt/P2Pplkelxzj9BYFajiWOtY2nHZNj4UnWY= +github.com/go-openapi/runtime v0.29.2 h1:UmwSGWNmWQqKm1c2MGgXVpC2FTGwPDQeUsBMufc5Yj0= +github.com/go-openapi/runtime v0.29.2/go.mod h1:biq5kJXRJKBJxTDJXAa00DOTa/anflQPhT0/wmjuy+0= +github.com/go-openapi/spec v0.22.3 h1:qRSmj6Smz2rEBxMnLRBMeBWxbbOvuOoElvSvObIgwQc= +github.com/go-openapi/spec v0.22.3/go.mod h1:iIImLODL2loCh3Vnox8TY2YWYJZjMAKYyLH2Mu8lOZs= +github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= +github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= +github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= +github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= +github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= +github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= +github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= +github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= +github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= +github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= +github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= +github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM= +github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= +github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= +github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= +github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= +github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= +github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= +github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= +github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= +github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= +github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= +github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= +github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= +github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= +github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw= +github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc= github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s= github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI= github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc= github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk= -github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA= +github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +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 v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 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-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= @@ -661,8 +724,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -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/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= @@ -672,13 +735,15 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= -github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/godbus/dbus/v5 v5.2.0 h1:3WexO+U+yg9T70v9FdHr9kCxYlazaAXUhx2VMkbfax8= +github.com/godbus/dbus/v5 v5.2.0/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= +github.com/godoc-lint/godoc-lint v0.11.2 h1:Bp0FkJWoSdNsBikdNgIcgtaoo+xz6I/Y9s5WSBQUeeM= +github.com/godoc-lint/godoc-lint v0.11.2/go.mod h1:iVpGdL1JCikNH2gGeAn3Hh+AgN5Gx/I/cxV+91L41jo= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= @@ -694,9 +759,7 @@ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8J github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -705,38 +768,43 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= +github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E= -github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= -github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U= +github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint v1.64.7 h1:Xk1EyxoXqZabn5b4vnjNKSjCx1whBK53NP+mzLfX7HA= -github.com/golangci/golangci-lint v1.64.7/go.mod h1:5cEsUQBSr6zi8XI8OjmcY2Xmliqc4iYL7YoPrL+zLJ4= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/golangci-lint/v2 v2.11.4 h1:GK+UlZBN5y7rh2PBnHA93XLSX6RaF7uhzJQ3JwU1wuA= +github.com/golangci/golangci-lint/v2 v2.11.4/go.mod h1:ODQDCASMA3VqfZYIbbQLpTRTzV7O/vjmIRF6u8NyFwI= +github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0= +github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10= +github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg= +github.com/golangci/misspell v0.8.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.24.1 h1:jsBCtxG8mM5wiUJDSGUqU0K7Mtr3w7Eyv00rw4DiZxI= -github.com/google/cel-go v0.24.1/go.mod h1:Hdf9TqOaTNSFQA1ybQaRqATVoK7m/zcf7IMhGXP5zI8= -github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= -github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ= +github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/certificate-transparency-go v1.3.2 h1:9ahSNZF2o7SYMaKaXhAumVEzXB2QaayzII9C8rv7v+A= +github.com/google/certificate-transparency-go v1.3.2/go.mod h1:H5FpMUaGa5Ab2+KCYsxg6sELw3Flkl7pGZzWdBoYLXs= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -748,14 +816,14 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0= -github.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.7 h1:24VGNpS0IwrOZ2ms2P1QE3Xa5X9p4phx0aUgzYzHW6I= +github.com/google/go-containerregistry v0.20.7/go.mod h1:Lx5LCZQjLH1QBaMPeGwsME9biPeo1lPx6lbGj/UmzgM= github.com/google/go-github/v62 v62.0.0 h1:/6mGCaRywZz9MuHyw9gD1CwsbmBX8GWsbFkwMmHdhl4= github.com/google/go-github/v62 v62.0.0/go.mod h1:EMxeUqGJq2xRu9DYBMwel/mr7kZrzUOfQmmpYrZn2a4= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE= -github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk= +github.com/google/go-replayers/grpcreplay v1.3.0 h1:1Keyy0m1sIpqstQmgz307zhiJ1pV4uIlFds5weTmxbo= +github.com/google/go-replayers/grpcreplay v1.3.0/go.mod h1:v6NgKtkijC0d3e3RW8il6Sy5sqRVUwoQa4mHOGEy8DI= github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk= github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -772,10 +840,10 @@ github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1 github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= -github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= -github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a h1:JJBdjSfqSy3mnDT0940ASQFghwcZ4y4cb6ttjAoXqwE= -github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a/go.mod h1:uqVAUVQLq8UY2hCDfmJ/+rtO3aw7qyhc90rCVEabEfI= +github.com/google/renameio/v2 v2.0.2 h1:qKZs+tfn+arruZZhQ7TKC/ergJunuJicWS6gLDt/dGw= +github.com/google/renameio/v2 v2.0.2/go.mod h1:OX+G6WHHpHq3NVj7cAOleLOwJfcQ1s3uUJQCrr78SWo= +github.com/google/rpmpack v0.7.1 h1:YdWh1IpzOjBz60Wvdw0TU0A5NWP+JTVHA5poDqwMO2o= +github.com/google/rpmpack v0.7.1/go.mod h1:h1JL16sUTWCLI/c39ox1rDaTBo3BXUQGjczVJyK4toU= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI= @@ -783,23 +851,25 @@ github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC 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/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/trillian v1.7.2 h1:EPBxc4YWY4Ak8tcuhyFleY+zYlbCDCa4Sn24e1Ka8Js= +github.com/google/trillian v1.7.2/go.mod h1:mfQJW4qRH6/ilABtPYNBerVJAJ/upxHLX81zxNQw05s= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/enterprise-certificate-proxy v0.3.9 h1:TOpi/QG8iDcZlkQlGlFUti/ZtyLkliXvHDcyUIMuFrU= +github.com/googleapis/enterprise-certificate-proxy v0.3.9/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.16.0 h1:iHbQmKLLZrexmb0OSsNGTeSTS0HO4YvFOG8g5E4Zd0Y= +github.com/googleapis/gax-go/v2 v2.16.0/go.mod h1:o1vfQjjNZn4+dPnRdl/4ZD7S9414Y4xA+a/6Icj6l14= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= github.com/gopacket/gopacket v1.5.0 h1:9s9fcSUVKFlRV97B77Bq9XNV3ly2gvvsneFMQUGjc+M= github.com/gopacket/gopacket v1.5.0/go.mod h1:i3NaGaqfoWKAr1+g7qxEdWsmfT+MXuWkAe9+THv8LME= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= -github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= -github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs= +github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw= github.com/goreleaser/chglog v0.6.1 h1:NZKiX8l0FTQPRzBgKST7knvNZmZ04f7PEGkN2wInfhE= github.com/goreleaser/chglog v0.6.1/go.mod h1:Bnnfo07jMZkaAb0uRNASMZyOsX6ROW6X1qbXqN3guUo= github.com/goreleaser/fileglob v1.3.0 h1:/X6J7U8lbDpQtBvGcwwPS6OpzkNVlVEsFUVRx9+k+7I= @@ -808,23 +878,22 @@ github.com/goreleaser/goreleaser v1.26.2 h1:1iY1HaXtRiMTrwy6KE1sNjkRjsjMi+9l0k6W github.com/goreleaser/goreleaser v1.26.2/go.mod h1:mHi6zr6fuuOh5eHdWWgyo/N8BWED5WEVtb/4GETc9jQ= github.com/goreleaser/nfpm/v2 v2.37.1 h1:RUmeEt8OlEVeSzKRrO5Vl5qVWCtUwx4j9uivGuRo5fw= github.com/goreleaser/nfpm/v2 v2.37.1/go.mod h1:q8+sZXFqn106/eGw+9V+I8+izFxZ/sJjrhwmEUxXhUg= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/nilerr v0.1.2 h1:S6nk8a9N8g062nsx63kUkF6AzbHGw7zzyHMcpu52xQU= +github.com/gostaticanalysis/nilerr v0.1.2/go.mod h1:A19UHhoY3y8ahoL7YKz6sdjDtduwTSI4CsymaC2htPA= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= @@ -832,12 +901,12 @@ github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +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/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +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/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -850,28 +919,44 @@ github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1T github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/arc/v2 v2.0.6 h1:4NU7uP5vSoK6TbaMj3NtY478TTAWLso/vL1gpNrInHg= github.com/hashicorp/golang-lru/arc/v2 v2.0.6/go.mod h1:cfdDIX05DWvYV6/shsxDfa/OVcRieOt+q4FnM8x+Xno= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/vault/api v1.22.0 h1:+HYFquE35/B74fHoIeXlZIP2YADVboaPjaSicHEZiH0= +github.com/hashicorp/vault/api v1.22.0/go.mod h1:IUZA2cDvr4Ok3+NtK2Oq/r+lJeXkeCrHRmqdyWfpmGM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= +github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/in-toto/attestation v1.1.2 h1:MBFn6lsMq6dptQZJBhalXTcWMb/aJy3V+GX3VYj/V1E= +github.com/in-toto/attestation v1.1.2/go.mod h1:gYFddHMZj3DiQ0b62ltNi1Vj5rC879bTmBbrv9CRHpM= +github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU= +github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/inspektor-gadget/netns v0.0.5-0.20230524185006-155d84c555d6 h1:fQqkJ+WkYfzy6BoUh32fr9uYrXfOGtsfw0skMQkfOic= -github.com/inspektor-gadget/netns v0.0.5-0.20230524185006-155d84c555d6/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= @@ -901,6 +986,14 @@ github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= +github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= @@ -908,24 +1001,22 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY= github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4= -github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= -github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs= -github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= @@ -944,37 +1035,32 @@ github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786 h1:N527AHMa79 github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786/go.mod h1:v4hqbTdfQngbVSZJVWUhGE/lbTFf9jb+ygmNUDQMuOs= github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM= github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y= github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= -github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= -github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/karamaru-alpha/copyloopvar v1.2.2 h1:yfNQvP9YaGQR7VaWLYcfZUlRP2eo2vhExWKxD/fP6q0= +github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY= +github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= +github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M= -github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= +github.com/kisielk/errcheck v1.10.0 h1:Lvs/YAHP24YKg08LA8oDw2z9fJVme090RAXd90S+rrw= +github.com/kisielk/errcheck v1.10.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -984,10 +1070,10 @@ 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/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= -github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kulti/thelper v0.7.1 h1:fI8QITAoFVLx+y+vSyuLBP+rcVIB8jKooNSCT2EiI98= +github.com/kulti/thelper v0.7.1/go.mod h1:NsMjfQEy6sd+9Kfw8kCP61W1I0nerGSYSFnGaxQkcbs= +github.com/kunwardeep/paralleltest v1.0.15 h1:ZMk4Qt306tHIgKISHWFJAO1IDQJLc6uDyJMLyncOb6w= +github.com/kunwardeep/paralleltest v1.0.15/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= @@ -996,38 +1082,45 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= -github.com/ldez/exptostd v0.4.2/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= -github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= -github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= -github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ= +github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM= +github.com/ldez/gomoddirectives v0.8.0 h1:JqIuTtgvFC2RdH1s357vrE23WJF2cpDCPFgA/TWDGpk= +github.com/ldez/gomoddirectives v0.8.0/go.mod h1:jutzamvZR4XYJLr0d5Honycp4Gy6GEg2mS9+2YX3F1Q= +github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= +github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/structtags v0.6.1 h1:bUooFLbXx41tW8SvkfwfFkkjPYvFFs59AAMgVg6DUBk= +github.com/ldez/structtags v0.6.1/go.mod h1:YDxVSgDy/MON6ariaxLF2X09bh19qL7MtGBN5MrvbdY= +github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= +github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 h1:WGrKdjHtWC67RX96eTkYD2f53NDHhrq/7robWTAfk4s= -github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491/go.mod h1:o158RFmdEbYyIZmXAbrvmJWesbyxlLKee6X64VPVuOc= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/letsencrypt/boulder v0.20251110.0 h1:J8MnKICeilO91dyQ2n5eBbab24neHzUpYMUIOdOtbjc= +github.com/letsencrypt/boulder v0.20251110.0/go.mod h1:ogKCJQwll82m7OVHWyTuf8eeFCjuzdRQlgnZcCl0V+8= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= +github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= -github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= -github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o= -github.com/mackerelio/go-osstat v0.2.5/go.mod h1:atxwWF+POUZcdtR1wnsUcQxTytoHG4uhl2AKKzrOajY= +github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= +github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= +github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= +github.com/mackerelio/go-osstat v0.2.6 h1:gs4U8BZeS1tjrL08tt5VUliVvSWP26Ai2Ob8Lr7f2i0= +github.com/mackerelio/go-osstat v0.2.6/go.mod h1:lRy8V9ZuHpuRVZh+vyTkODeDPl3/d5MgXHtLSaqG8bA= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= -github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= -github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= +github.com/maratori/testableexamples v1.0.1 h1:HfOQXs+XgfeRBJ+Wz0XfH+FHnoY9TVqL6Fcevpzy4q8= +github.com/maratori/testableexamples v1.0.1/go.mod h1:XE2F/nQs7B9N08JgyRmdGjYVGqxWwClLPCGSQhXQSrQ= +github.com/maratori/testpackage v1.1.2 h1:ffDSh+AgqluCLMXhM19f/cpvQAKygKAJXFl9aUjmbqs= +github.com/maratori/testpackage v1.1.2/go.mod h1:8F24GdVDFW5Ew43Et02jamrVMNXLUNaOynhDssITGfc= 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/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= @@ -1040,21 +1133,17 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZMYDR+NGImiFvErt6VWfIRPuGM+vyjiEdkmIw= +github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-mastodon v0.0.8 h1:UgKs4SmQ5JeawxMIPP7NQ9xncmOXA+5q6jYk4erR7vk= github.com/mattn/go-mastodon v0.0.8/go.mod h1:8YkqetHoAVEktRkK15qeiv/aaIMfJ/Gc89etisPZtHU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= +github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo= github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= @@ -1068,22 +1157,22 @@ github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuri github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= github.com/mdlayher/netlink v1.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU= -github.com/mdlayher/netlink v1.10.0 h1:K7NHm0iQh2nOtfsj/YNNSN1s7T5JGtNCNwP66OKNiEw= -github.com/mdlayher/netlink v1.10.0/go.mod h1:YBnl5BXsCoRuwBjKKlZ+aYmEoq0r12FDA/3JC+94KDg= +github.com/mdlayher/netlink v1.11.0 h1:Cot7ixQZL6P/pxRFB4z3jRdGPYeZosFT+WHS3sMXy8Y= +github.com/mdlayher/netlink v1.11.0/go.mod h1:rMwDzh42W85uW3yTtiTRZFX9uway98aDQ5i+D8Jq4g4= github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= -github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= -github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= +github.com/mdlayher/socket v0.6.0 h1:ScZPaAGyO1icQnbFrhPM8mnXyMu9qukC1K4ZoM2IQKU= +github.com/mdlayher/socket v0.6.0/go.mod h1:q7vozUAnxSqnjHc12Fik5yUKIzfZ8ITCfMkhOtE9z18= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= -github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= -github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= +github.com/mgechev/revive v1.15.0 h1:vJ0HzSBzfNyPbHKolgiFjHxLek9KUijhqh42yGoqZ8Q= +github.com/mgechev/revive v1.15.0/go.mod h1:LlAKO3QQe9OJ0pVZzI2GPa8CbXGZ/9lNpCGvK4T/a8A= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microsoft/ApplicationInsights-Go v0.4.4 h1:G4+H9WNs6ygSCe6sUyxRc2U81TI5Es90b2t/MwX5KqY= github.com/microsoft/ApplicationInsights-Go v0.4.4/go.mod h1:fKRUseBqkw6bDiXTs3ESTiU/4YTIHsQS4W3fP2ieF4U= -github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= -github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= +github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA= +github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -1092,35 +1181,32 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 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/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/moby/api v1.54.0 h1:7kbUgyiKcoBhm0UrWbdrMs7RX8dnwzURKVbZGy2GnL0= +github.com/moby/moby/api v1.54.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc= +github.com/moby/moby/client v0.3.0 h1:UUGL5okry+Aomj3WhGt9Aigl3ZOxZGqR7XPo+RLPlKs= +github.com/moby/moby/client v0.3.0/go.mod h1:HJgFbJRvogDQjbM8fqc1MCEm4mIAGMLjXbgwoZp6jCQ= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= 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/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= -github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= 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/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/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= -github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= @@ -1129,9 +1215,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= -github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= -github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI= @@ -1140,13 +1225,10 @@ github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbY github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg= github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= -github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= @@ -1159,25 +1241,24 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= +github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= -github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= +github.com/nunnatsa/ginkgolinter v0.23.0 h1:x3o4DGYOWbBMP/VdNQKgSj+25aJKx2Pe6lHr8gBcgf8= +github.com/nunnatsa/ginkgolinter v0.23.0/go.mod h1:9qN1+0akwXEccwV1CAcCDfcoBlWXHB+ML9884pL4SZ4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -1211,19 +1292,18 @@ github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH github.com/pborman/getopt v0.0.0-20180811024354-2b5b3bfb099b/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/peterbourgon/diskv v2.0.2-0.20180312054125-0646ccaebea1+incompatible h1:FhnA4iH8T/yYW+AolPONZjGE897wxj3MAzfEbrZkSYw= github.com/peterbourgon/diskv v2.0.2-0.20180312054125-0646ccaebea1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe h1:vHpqOnPlnkba8iSxU4j/CvDSS9J4+F4473esQsYLGoE= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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= @@ -1234,35 +1314,25 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= -github.com/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= -github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= -github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/quasilyte/go-ruleguard v0.4.5 h1:AGY0tiOT5hJX9BTdx/xBdoCubQUAE2grkqY2lSwvZcA= +github.com/quasilyte/go-ruleguard v0.4.5/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= +github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY= +github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -1275,73 +1345,90 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1 h1:+o7rrBoj54t8fqQSmnwRLdLzp5 github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1/go.mod h1:bWIjbxmrAk9eKGg9LSko3oQefoYGyWV4xzNS55PgL60= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 h1:LJF39lvUagUpKfL2/gZIp5vHv3AwXt9zOZ/Xual/CzI= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1/go.mod h1:VAY1vDpD/dLwfw/wU5SsexXNhCO9DjhRoGkmJeFONoE= -github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= -github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI= +github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 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/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4= -github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= +github.com/rubenv/sql-migrate v1.8.1 h1:EPNwCvjAowHI3TnZ+4fQu3a915OpnQoPAjTXCGOy2U0= +github.com/rubenv/sql-migrate v1.8.1/go.mod h1:BTIKBORjzyxZDS6dzoiw6eAFYJ1iNlGAtjn4LGeVjS8= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= -github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= -github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= -github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= +github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g= +github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= +github.com/ryanrolds/sqlclosecheck v0.6.0 h1:pEyL9okISdg1F1SEpJNlrEotkTGerv5BMk7U4AG0eVg= +github.com/ryanrolds/sqlclosecheck v0.6.0/go.mod h1:xyX16hsDaCMXHrMJ3JMzGf5OpDfHTOTTQrT7HOFUmeU= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/safchain/ethtool v0.7.0 h1:rlJzfDetsVvT61uz8x1YIcFn12akMfuPulHtZjtb7Is= github.com/safchain/ethtool v0.7.0/go.mod h1:MenQKEjXdfkjD3mp2QdCk8B/hwvkrlOTm/FD4gTpFxQ= -github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= -github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= -github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sasha-s/go-deadlock v0.3.6 h1:TR7sfOnZ7x00tWPfD397Peodt57KzMDo+9Ae9rMiUmw= +github.com/sasha-s/go-deadlock v0.3.6/go.mod h1:CUqNyyvMxTyjFqDT7MRg9mb4Dv/btmGTqSR+rky/UXo= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI= +github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A= +github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= +github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= +github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= -github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= -github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= -github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g= -github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE= +github.com/secure-systems-lab/go-securesystemslib v0.10.0 h1:l+H5ErcW0PAehBNrBxoGv1jjNpGYdZ9RcheFkB2WI14= +github.com/secure-systems-lab/go-securesystemslib v0.10.0/go.mod h1:MRKONWmRoFzPNQ9USRF9i1mc7MvAVvF1LlW8X5VWDvk= +github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08 h1:AoLtJX4WUtZkhhUUMFy3GgecAALp/Mb4S1iyQOA2s0U= +github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08/go.mod h1:+XLCJiRE95ga77XInNELh2M6zQP+PdqiT9Zpm0D9Wpk= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= +github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sigstore/cosign/v2 v2.2.4 h1:iY4vtEacmu2hkNj1Fh+8EBqBwKs2DHM27/lbNWDFJro= -github.com/sigstore/cosign/v2 v2.2.4/go.mod h1:JZlRD2uaEjVAvZ1XJ3QkkZJhTqSDVtLaet+C/TMR81Y= -github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8= -github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc= -github.com/sigstore/sigstore v1.8.3 h1:G7LVXqL+ekgYtYdksBks9B38dPoIsbscjQJX/MGWkA4= -github.com/sigstore/sigstore v1.8.3/go.mod h1:mqbTEariiGA94cn6G3xnDiV6BD8eSLdL/eA7bvJ0fVs= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sigstore/cosign/v2 v2.6.2 h1:mi6EAUJoPZ+yuyooU7m06a1DZWJouwYgh9a67L9tm2M= +github.com/sigstore/cosign/v2 v2.6.2/go.mod h1:g+P/LgYyJkC85WGGDho7yySl3C6xTJzzpLm21ZV+E6s= +github.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY= +github.com/sigstore/protobuf-specs v0.5.0/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc= +github.com/sigstore/rekor v1.5.0 h1:rL7SghHd5HLCtsCrxw0yQg+NczGvM75EjSPPWuGjaiQ= +github.com/sigstore/rekor v1.5.0/go.mod h1:D7JoVCUkxwQOpPDNYeu+CE8zeBC18Y5uDo6tF8s2rcQ= +github.com/sigstore/rekor-tiles/v2 v2.0.1 h1:1Wfz15oSRNGF5Dzb0lWn5W8+lfO50ork4PGIfEKjZeo= +github.com/sigstore/rekor-tiles/v2 v2.0.1/go.mod h1:Pjsbhzj5hc3MKY8FfVTYHBUHQEnP0ozC4huatu4x7OU= +github.com/sigstore/sigstore v1.10.4 h1:ytOmxMgLdcUed3w1SbbZOgcxqwMG61lh1TmZLN+WeZE= +github.com/sigstore/sigstore v1.10.4/go.mod h1:tDiyrdOref3q6qJxm2G+JHghqfmvifB7hw+EReAfnbI= +github.com/sigstore/sigstore-go v1.1.4 h1:wTTsgCHOfqiEzVyBYA6mDczGtBkN7cM8mPpjJj5QvMg= +github.com/sigstore/sigstore-go v1.1.4/go.mod h1:2U/mQOT9cjjxrtIUeKDVhL+sHBKsnWddn8URlswdBsg= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.3 h1:D/FRl5J9UYAJPGZRAJbP0dH78pfwWnKsyCSBwFBU8CI= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.3/go.mod h1:2GIWuNvTRMvrzd0Nl8RNqxrt9H7X0OBStwOSzGYRjYw= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.3 h1:k5VMLf/ms7hh6MLgVoorM0K+hSMwZLXoywlxh4CXqP8= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.3/go.mod h1:S1Bp3dmP7jYlXcGLAxG81wRbE01NIZING8ZIy0dJlAI= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.3 h1:AVWs0E6rVZMoDTE0Iyezrpo1J6RlI5B4QZhAC4FLE30= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.3/go.mod h1:nxQYF0D6u7mVtiP1azj1YVDIrtz7S0RYCVTqUG8IcCk= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.3 h1:lJSdaC/aOlFHlvqmmV696n1HdXLMLEKGwpNZMV0sKts= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.3/go.mod h1:b2rV9qPbt/jv/Yy75AIOZThP8j+pe1ZdLEjOwmjPdoA= +github.com/sigstore/timestamp-authority/v2 v2.0.3 h1:sRyYNtdED/ttLCMdaYnwpf0zre1A9chvjTnCmWWxN8Y= +github.com/sigstore/timestamp-authority/v2 v2.0.3/go.mod h1:mDaHxkt3HmZYoIlwYj4QWo0RUr7VjYU52aVO5f5Qb3I= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= -github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= -github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= -github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/slack-go/slack v0.13.0 h1:7my/pR2ubZJ9912p9FtvALYpbt0cQPAqkRy2jaSI1PQ= github.com/slack-go/slack v0.13.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= @@ -1350,37 +1437,35 @@ github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sonatard/noctx v0.5.1 h1:wklWg9c9ZYugOAk7qG4yP4PBrlQsmSLPTvW1K4PRQMs= +github.com/sonatard/noctx v0.5.1/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= -github.com/spiffe/spire-api-sdk v1.12.0 h1:xx6PAsoBTvMtNe7h5dGS+/SyVZccudAQg/vB9P/XPec= -github.com/spiffe/spire-api-sdk v1.12.0/go.mod h1:4uuhFlN6KBWjACRP3xXwrOTNnvaLp1zJs8Lribtr4fI= +github.com/spiffe/spire-api-sdk v1.14.0 h1:72Ywh9Mq/Zd2irveBEFIh0LFLG8/KYTltkVkBluPd0A= +github.com/spiffe/spire-api-sdk v1.14.0/go.mod h1:9hXJcMzatM1KwAtBDO3s6HccDCic++/5c2yOc5Iln8Y= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= -github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= +github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= +github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -1401,15 +1486,17 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= -github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw= -github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg= +github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU= +github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= +github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug= +github.com/theupdateframework/go-tuf/v2 v2.3.0 h1:gt3X8xT8qu/HT4w+n1jgv+p7koi5ad8XEkLXXZqG9AA= +github.com/theupdateframework/go-tuf/v2 v2.3.0/go.mod h1:xW8yNvgXRncmovMLvBxKwrKpsOwJZu/8x+aB0KtFcdw= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -1420,37 +1507,51 @@ 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/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= -github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= -github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= +github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= +github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= +github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tink-crypto/tink-go-awskms/v2 v2.1.0 h1:N9UxlsOzu5mttdjhxkDLbzwtEecuXmlxZVo/ds7JKJI= +github.com/tink-crypto/tink-go-awskms/v2 v2.1.0/go.mod h1:PxSp9GlOkKL9rlybW804uspnHuO9nbD98V/fDX4uSis= +github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0 h1:3B9i6XBXNTRspfkTC0asN5W0K6GhOSgcujNiECNRNb0= +github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0/go.mod h1:jY5YN2BqD/KSCHM9SqZPIpJNG/u3zwfLXHgws4x2IRw= +github.com/tink-crypto/tink-go-hcvault/v2 v2.3.0 h1:6nAX1aRGnkg2SEUMwO5toB2tQkP0Jd6cbmZ/K5Le1V0= +github.com/tink-crypto/tink-go-hcvault/v2 v2.3.0/go.mod h1:HOC5NWW1wBI2Vke1FGcRBvDATkEYE7AUDiYbXqi2sBw= +github.com/tink-crypto/tink-go/v2 v2.6.0 h1:+KHNBHhWH33Vn+igZWcsgdEPUxKwBMEe0QC60t388v4= +github.com/tink-crypto/tink-go/v2 v2.6.0/go.mod h1:2WbBA6pfNsAfBwDCggboaHeB2X29wkU8XHtGwh2YIk8= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= -github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= -github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVFL27Of9is= +github.com/tomarrell/wrapcheck/v2 v2.12.0/go.mod h1:AQhQuZd0p7b6rfW+vUwHm5OMCGgp63moQ9Qr/0BpIWo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= -github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= -github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/transparency-dev/formats v0.0.0-20251017110053-404c0d5b696c h1:5a2XDQ2LiAUV+/RjckMyq9sXudfrPSuCY4FuPC1NyAw= +github.com/transparency-dev/formats v0.0.0-20251017110053-404c0d5b696c/go.mod h1:g85IafeFJZLxlzZCDRu4JLpfS7HKzR+Hw9qRh3bVzDI= +github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4= +github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= github.com/ultraware/funlen v0.2.0/go.mod h1:ZE0q4TsJ8T1SQcjmkhN/w+MceuatI6pBFSxxyteHIJA= github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSWoFa+g= github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= -github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= -github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= -github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= -github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/uudashr/gocognit v1.2.1 h1:CSJynt5txTnORn/DkhiB4mZjwPuifyASC8/6Q0I/QS4= +github.com/uudashr/gocognit v1.2.1/go.mod h1:acaubQc6xYlXFEMb9nWX2dYBzJ/bIjEkc1zzvyIZg5Q= +github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU= +github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= +github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= +github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= +github.com/vishvananda/netlink v1.3.2-0.20260109214200-c6faf428e8f8 h1:/EaCkwYyCH9rDgccb78ZTaGwo7UGjjdh0iyCa3+miRs= +github.com/vishvananda/netlink v1.3.2-0.20260109214200-c6faf428e8f8/go.mod h1:lEui7SPMd9fgxzHVGRAvTxsBGCF6PRH81o2kLWLWHgw= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= -github.com/wagoodman/go-progress v0.0.0-20220614130704-4b1c25a33c7c h1:gFwUKtkv6QzQsFdIjvPqd0Qdw42DHUEbbUdiUTI1uco= -github.com/wagoodman/go-progress v0.0.0-20220614130704-4b1c25a33c7c/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA= +github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 h1:0KGbf+0SMg+UFy4e1A/CPVvXn21f1qtWdeJwxZFoQG8= +github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/cbor-gen v0.1.1-0.20240311221002-68b9f235c302 h1:MhInbXe4SzcImAKktUvWBCWZgcw6MYf5NfumTj1BhAw= @@ -1463,25 +1564,36 @@ github.com/xanzy/go-gitlab v0.105.0 h1:3nyLq0ESez0crcaM19o5S//SvezOQguuIHZ3wgX64 github.com/xanzy/go-gitlab v0.105.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -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= -github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= -github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= +github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= +github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ= +github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns= +github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ= +github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18= +github.com/ysmood/got v0.40.0 h1:ZQk1B55zIvS7zflRrkGfPDrPG3d7+JOza1ZkNxcc74Q= +github.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg= +github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= +github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU= +github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1489,24 +1601,30 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= +github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= gitlab.com/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8= gitlab.com/digitalxero/go-conventional-commit v1.0.7/go.mod h1:05Xc2BFsSyC5tKhK0y+P3bs0AwUtNuTp+mTpbCU/DZ0= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= -go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= -go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= -go.etcd.io/etcd/api/v3 v3.5.21 h1:A6O2/JDb3tvHhiIz3xf9nJ7REHvtEFJJ3veW3FbCnS8= -go.etcd.io/etcd/api/v3 v3.5.21/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY= -go.etcd.io/etcd/client/pkg/v3 v3.5.21 h1:lPBu71Y7osQmzlflM9OfeIV2JlmpBjqBNlLtcoBqUTc= -go.etcd.io/etcd/client/pkg/v3 v3.5.21/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs= -go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY= -go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= +go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= +go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= +go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50= +go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA= +go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= +go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= +go.etcd.io/etcd/api/v3 v3.6.7 h1:7BNJ2gQmc3DNM+9cRkv7KkGQDayElg8x3X+tFDYS+E0= +go.etcd.io/etcd/api/v3 v3.6.7/go.mod h1:xJ81TLj9hxrYYEDmXTeKURMeY3qEDN24hqe+q7KhbnI= +go.etcd.io/etcd/client/pkg/v3 v3.6.7 h1:vvzgyozz46q+TyeGBuFzVuI53/yd133CHceNb/AhBVs= +go.etcd.io/etcd/client/pkg/v3 v3.6.7/go.mod h1:2IVulJ3FZ/czIGl9T4lMF1uxzrhRahLqe+hSgy+Kh7Q= +go.etcd.io/etcd/client/v3 v3.6.7 h1:9WqA5RpIBtdMxAy1ukXLAdtg2pAxNqW5NUoO2wQrE6U= +go.etcd.io/etcd/client/v3 v3.6.7/go.mod h1:2XfROY56AXnUqGsvl+6k29wrwsSbEh1lAouQB1vHpeE= +go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= +go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= @@ -1517,50 +1635,50 @@ go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK2 go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 h1:GuQXpvSXNjpswpweIem84U9BNauqHHi2w1GtNAalvpM= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0/go.mod h1:CkmxekdHco4d7thFJNPQ7Mby4jMBgZUclnrxT4e+ryk= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= 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/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 h1:ZVg+kCXxd9LtAaQNKBxAvJ5NpMf7LpvEr4MIZqb0TMQ= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0/go.mod h1:hh0tMeZ75CCXrHd9OXRYxTlCAdxcXioWHFIpYw2rZu8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0/go.mod h1:0Lr9vmGKzadCTgsiBydxr6GEZ8SsZ7Ks53LzjWG5Ar4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 h1:0NIXxOCFx+SKbhCVxwl3ETG8ClLPAa0KuKV6p3yhxP8= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0/go.mod h1:ChZSJbbfbl/DcRZNc9Gqh6DYGlfjw4PvO1pEOZH1ZsE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= -go.opentelemetry.io/otel/exporters/prometheus v0.57.0 h1:AHh/lAP1BHrY5gBwk8ncc25FXWm/gmmY3BX258z5nuk= -go.opentelemetry.io/otel/exporters/prometheus v0.57.0/go.mod h1:QpFWz1QxqevfjwzYdbMb4Y1NnlJvqSGwyuU0B4iuc9c= +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/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +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/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE= +go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0 h1:k6KdfZk72tVW/QVZf60xlDziDvYAePj5QHwoQvrB2m8= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0/go.mod h1:5Y3ZJLqzi/x/kYtrSrPSx7TFI/SGsL7q2kME027tH6I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 h1:PB3Zrjs1sG1GBX51SXyTSoOTqcDglmsk7nT6tkKPb/k= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0/go.mod h1:U2R3XyVPzn0WX7wOIypPuptulsMcPDPs/oiSVOMVnHY= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1xzhKrotaHy3/KXdPhlWARrCgK+eqUY= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= -go.opentelemetry.io/otel/log v0.11.0 h1:c24Hrlk5WJ8JWcwbQxdBqxZdOK7PcP/LFtOtwpDTe3Y= -go.opentelemetry.io/otel/log v0.11.0/go.mod h1:U/sxQ83FPmT29trrifhQg+Zj2lo1/IPN1PF6RTFqdwc= +go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4= +go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes= 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.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= -go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= -go.opentelemetry.io/otel/sdk/log v0.11.0 h1:7bAOpjpGglWhdEzP8z0VXc4jObOiDEwr3IYbhBnjk2c= -go.opentelemetry.io/otel/sdk/log v0.11.0/go.mod h1:dndLTxZbwBstZoqsJB3kGsRPkpAgaJrWfQg3lhlHFFY= -go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= -go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +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/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI= +go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4= +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 v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= -go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +go.step.sm/crypto v0.75.0 h1:UAHYD6q6ggYyzLlIKHv1MCUVjZIesXRZpGTlRC/HSHw= +go.step.sm/crypto v0.75.0/go.mod h1:wwQ57+ajmDype9mrI/2hRyrvJd7yja5xVgWYqpUN3PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -1574,26 +1692,25 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= -go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U= +go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -gocloud.dev v0.37.0 h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro= -gocloud.dev v0.37.0/go.mod h1:7/O4kqdInCNsc6LqgmuFnS0GRew4XNNYWpA44yQnwco= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +gocloud.dev v0.40.0 h1:f8LgP+4WDqOG/RXoUcyLpeIAGOcAbZrZbDQCUee10ng= +gocloud.dev v0.40.0/go.mod h1:drz+VyYNBvrMTW0KZiBAYEdl8lbNZx+OQ7oQvdrFmSQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1609,15 +1726,15 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 h1:qWFG1Dj7TBjOjOvhEOkmyGPVoquqUKnIU0lEVLp8xyk= +golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= 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= @@ -1631,24 +1748,19 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1656,7 +1768,6 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1670,22 +1781,18 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= +golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1700,15 +1807,11 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1726,7 +1829,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1738,56 +1840,49 @@ golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= -golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1801,12 +1896,9 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= @@ -1815,14 +1907,12 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -1831,34 +1921,30 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -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= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.223.0 h1:JUTaWEriXmEy5AhvdMgksGGPEFsYfUKaPEYXd4c3Wvc= -google.golang.org/api v0.223.0/go.mod h1:C+RS7Z+dDwds2b+zoAk5hN/eSfsiCn0UDrYof/M4d2M= +google.golang.org/api v0.260.0 h1:XbNi5E6bOVEj/uLXQRlt6TKuEzMD7zvW/6tNwltE4P4= +google.golang.org/api v0.260.0/go.mod h1:Shj1j0Phr/9sloYrKomICzdYgsSDImpTxME8rGLaZ/o= 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-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 h1:vmC/ws+pLzWjj/gzApyoZuSVrDtF1aod4u/+bbj8hgM= -google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 h1:GvESR9BIyHUahIb0NcTum6itIWtdoglGX+rnGxm2934= +google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:yJ2HH4EHEDTd3JiLmhds6NkJ17ITVYOdV3m3VKOnws0= +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-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 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 v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1870,13 +1956,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1887,11 +1968,9 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/dnaeon/go-vcr.v3 v3.2.0 h1:Rltp0Vf+Aq0u4rQXgmXgtgoRDStTnFN83cWgSGSoRzM= gopkg.in/dnaeon/go-vcr.v3 v3.2.0/go.mod h1:2IMOnnlx9I6u9x+YBsM3tAMx6AlOxnJ0pWxQAzZ79Ag= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= @@ -1904,7 +1983,6 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1918,76 +1996,82 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -helm.sh/helm/v3 v3.17.4 h1:GK+vgn9gKCyoH44+f3B5zpA78iH3AK4ywIInDEmmn/g= -helm.sh/helm/v3 v3.17.4/go.mod h1:+uJKMH/UiMzZQOALR3XUf3BLIoczI2RKKD6bMhPh4G8= +helm.sh/helm/v3 v3.20.2 h1:binM4rvPx5DcNsa1sIt7UZi55lRbu3pZUFmQkSoRh48= +helm.sh/helm/v3 v3.20.2/go.mod h1:Fl1kBaWCpkUrM6IYXPjQ3bdZQfFrogKArqptvueZ6Ww= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= -honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -k8s.io/api v0.32.4 h1:kw8Y/G8E7EpNy7gjB8gJZl3KJkNz8HM2YHrZPtAZsF4= -k8s.io/api v0.32.4/go.mod h1:5MYFvLvweRhyKylM3Es/6uh/5hGp0dg82vP34KifX4g= -k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= -k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= -k8s.io/apimachinery v0.32.4 h1:8EEksaxA7nd7xWJkkwLDN4SvWS5ot9g6Z/VZb3ju25I= -k8s.io/apimachinery v0.32.4/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8= -k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc= -k8s.io/cli-runtime v0.32.3 h1:khLF2ivU2T6Q77H97atx3REY9tXiA3OLOjWJxUrdvss= -k8s.io/cli-runtime v0.32.3/go.mod h1:vZT6dZq7mZAca53rwUfdFSZjdtLyfF61mkf/8q+Xjak= -k8s.io/client-go v0.32.4 h1:zaGJS7xoYOYumoWIFXlcVrsiYioRPrXGO7dBfVC5R6M= -k8s.io/client-go v0.32.4/go.mod h1:k0jftcyYnEtwlFW92xC7MTtFv5BNcZBr+zn9jPlT9Ic= -k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= -k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= +honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= +honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= +k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= +k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= +k8s.io/apiextensions-apiserver v0.35.3 h1:2fQUhEO7P17sijylbdwt0nBdXP0TvHrHj0KeqHD8FiU= +k8s.io/apiextensions-apiserver v0.35.3/go.mod h1:tK4Kz58ykRpwAEkXUb634HD1ZAegEElktz/B3jgETd8= +k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= +k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apiserver v0.35.3 h1:D2eIcfJ05hEAEewoSDg+05e0aSRwx8Y4Agvd/wiomUI= +k8s.io/apiserver v0.35.3/go.mod h1:JI0n9bHYzSgIxgIrfe21dbduJ9NHzKJ6RchcsmIKWKY= +k8s.io/cli-runtime v0.35.3 h1:UZq4ipNimtzBmhN7PPKbfAdqo8quK0H0UdGl6qAQnqI= +k8s.io/cli-runtime v0.35.3/go.mod h1:O7MUmCqcKSd5xI+O5X7/pRkB5l0O2NIhOdUVwbHLXu4= +k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= +k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= +k8s.io/code-generator v0.35.3 h1:NDGCLkEm6Ho65wTdSe2EgErmmtsrezOPwwOchlNc6FQ= +k8s.io/code-generator v0.35.3/go.mod h1:LAVriRGXQusHQ0Ns64SE1ublSswm1KrK7cXn0GuQETg= +k8s.io/component-base v0.35.3 h1:mbKbzoIMy7JDWS/wqZobYW1JDVRn/RKRaoMQHP9c4P0= +k8s.io/component-base v0.35.3/go.mod h1:IZ8LEG30kPN4Et5NeC7vjNv5aU73ku5MS15iZyvyMYk= +k8s.io/component-helpers v0.35.3 h1:Rl2p3wNMC0YU21rziLkWXavr7MwkB5Td3lNZ/+gYGm8= +k8s.io/component-helpers v0.35.3/go.mod h1:8BkyfcBA6XsCtFYxDB+mCfZqM6P39Aco12AKigNn0C8= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= -k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI= -k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg= -k8s.io/metrics v0.32.3 h1:2vsBvw0v8rIIlczZ/lZ8Kcqk9tR6Fks9h+dtFNbc2a4= -k8s.io/metrics v0.32.3/go.mod h1:9R1Wk5cb+qJpCQon9h52mgkVCcFeYxcY+YkumfwHVCU= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/kubectl v0.35.3 h1:1KqSYXk/sodU7VeDvK6atX2kAGUZd2QTeR5K7Hb9r9w= +k8s.io/kubectl v0.35.3/go.mod h1:GPHxZqRe+u/i3gTBoVQHeIyq2NilfNPj9hDWeuN3x5s= +k8s.io/metrics v0.35.3 h1:WonA18pEwrtb7a6XfhFg1ZY1Le0RFkcEw7CFApMTZos= +k8s.io/metrics v0.35.3/go.mod h1:/O8UBb5QVyAekR2QvL/WWxskpdV1wVSEl4MSLAy4Ql4= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= -oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= -oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0 h1:gw3Xs5UzvvkhL8OEp1FF2AdHST3nNvWNjxZ6raSOD6w= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.16.0/go.mod h1:JtYQ5YsO3jVngwsQktrm+gCB43BrQ3tPAS1YyooPxhs= -sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3 h1:PiQy1U20uPkBgdpbERnX3BZ4bB6tljBJKU9wXmn1GrI= -sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.5.3/go.mod h1:eBK7J+xfuzLATTK5ALuERxsZv7O4kncWnCW5ILCLX0w= -sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= -sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= +mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU= +oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= +oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0 h1:2dTd+O9qw29HmFJLM1ndXFzZHgsHSMjypZut4Aswrtg= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0/go.mod h1:/9zZbyG796jn0eDbnf7arSRHwj+CxObf1Mvln/+UbVs= +sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 h1:lJR9oMwgaUvKqWp+Pt2F/dpqEpiU8PpxELV5cA65rGE= +sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0/go.mod h1:xSnyMWmeA+LeCdpM15e56eZZOVjd4SXUVvFrfSQISdI= +sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= +sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5 h1:eOG9vIdpeOc/NI5RStnrYrEL4Crf66SHtfpVXwvRaNc= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5/go.mod h1:Cq9jUhwSYol5tNB0O/1vLYxNV9KqnhpvEa6HvJ1w0wY= -sigs.k8s.io/controller-tools v0.16.5 h1:5k9FNRqziBPwqr17AMEPPV/En39ZBplLAdOwwQHruP4= -sigs.k8s.io/controller-tools v0.16.5/go.mod h1:8vztuRVzs8IuuJqKqbXCSlXcw+lkAv/M2sTpg55qjMY= -sigs.k8s.io/gateway-api v1.2.1-0.20250319040149-e8b8afabf889 h1:oCrmvARaph9Rzu+8QWnmKAjgyRqwmZ2J6llfYto8IR8= -sigs.k8s.io/gateway-api v1.2.1-0.20250319040149-e8b8afabf889/go.mod h1:jXin3F66taaYeu7CP6Bsiv+4qBgwZSQ43uF6vZ8T6yw= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI5uk= +sigs.k8s.io/controller-tools v0.19.0/go.mod h1:y5HY/iNDFkmFla2CfQoVb2AQXMsBk4ad84iR1PLANB0= +sigs.k8s.io/gateway-api v1.4.0-rc.2 h1:1JVw4/b7ug+3AgWDQDSPAnovePYBmSiZ1H1muzgQv8s= +sigs.k8s.io/gateway-api v1.4.0-rc.2/go.mod h1:AR5RSqciWP98OPckEjOjh2XJhAe2Na4LHyXD2FUY7Qk= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kind v0.23.0 h1:8fyDGWbWTeCcCTwA04v4Nfr45KKxbSPH1WO9K+jVrBg= sigs.k8s.io/kind v0.23.0/go.mod h1:ZQ1iZuJLh3T+O8fzhdi3VWcFTzsdXtNv2ppsHc8JQ7s= -sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= -sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= -sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= -sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= -sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0 h1:LChl5QBr39XNzUjscGlfBJYjyclDru70cLujcC8Vn/M= -sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0/go.mod h1:M1Zjh0Jn/Z5e/2JHsZyEeLMw0qGBBmkJqEOc+OceERY= -sigs.k8s.io/mcs-api/controllers v0.0.0-20250224121229-6c631f4730d0 h1:tchq4R6n8HQHTn+Gkg2wW+MSDx7hD48quYAuvFVmjt0= -sigs.k8s.io/mcs-api/controllers v0.0.0-20250224121229-6c631f4730d0/go.mod h1:+ZTKacf5PGpIh+NjwMJqloeXJspb8wxkOgWB4m0L+xI= -sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= +sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= +sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= +sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= +sigs.k8s.io/mcs-api v0.3.1-0.20260224125735-0f775a3eff97 h1:SCB1P+SmtFETI9jkWt7bRVYXPeFPtT1zFtskvfXYetU= +sigs.k8s.io/mcs-api v0.3.1-0.20260224125735-0f775a3eff97/go.mod h1:zZ5CK8uS6HaLkxY4HqsmcBHfzHuNMrY2uJy8T7jffK4= +sigs.k8s.io/mcs-api/controllers v0.0.0-20260403094305-4b9911b73f14 h1:YSv/NHNrhf9K+AEGqqwkl6QW3Y6yLXU8YRfKZ7dfjb4= +sigs.k8s.io/mcs-api/controllers v0.0.0-20260403094305-4b9911b73f14/go.mod h1:IEVANHiCGLNsCWuPsZCJhCVzeWavUmxpJ8XgpTt9MpM= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= -software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= -software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= +software.sslmate.com/src/go-pkcs12 v0.7.0 h1:Db8W44cB54TWD7stUFFSWxdfpdn6fZVcDl0w3R4RVM0= +software.sslmate.com/src/go-pkcs12 v0.7.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= diff --git a/operator/cilium-crds/k8s/apis/cell.go b/operator/cilium-crds/k8s/apis/cell.go index 4c6d86b962..37c8bfc5b7 100644 --- a/operator/cilium-crds/k8s/apis/cell.go +++ b/operator/cilium-crds/k8s/apis/cell.go @@ -8,8 +8,8 @@ package apis import ( "fmt" + "log/slog" - "github.com/sirupsen/logrus" "github.com/spf13/pflag" k8sClient "github.com/cilium/cilium/pkg/k8s/client" @@ -48,7 +48,7 @@ type RegisterCRDsFunc func(k8sClient.Clientset) error type params struct { cell.In - Logger logrus.FieldLogger + Logger *slog.Logger Lifecycle cell.Lifecycle Clientset k8sClient.Clientset diff --git a/operator/cilium-crds/k8s/apis/register.go b/operator/cilium-crds/k8s/apis/register.go index 73732bb1ce..4d6c31514a 100644 --- a/operator/cilium-crds/k8s/apis/register.go +++ b/operator/cilium-crds/k8s/apis/register.go @@ -101,8 +101,10 @@ func createCRD(crdVersionedName, crdMetaName string) func(clientset apiextension clientset, constructV1CRD(crdMetaName, ciliumCRD), crdhelpers.NewDefaultPoller(), - k8sconst.CustomResourceDefinitionSchemaVersionKey, - versioncheck.MustVersion(k8sconst.CustomResourceDefinitionSchemaVersion), + crdhelpers.NeedsUpdateV1Factory( + k8sconst.CustomResourceDefinitionSchemaVersionKey, + versioncheck.MustVersion(k8sconst.CustomResourceDefinitionSchemaVersion), + ), ) if err != nil { return fmt.Errorf("Unable to create CRD %s: %w", crdMetaName, err) diff --git a/operator/cilium-crds/k8s/fakeresource.go b/operator/cilium-crds/k8s/fakeresource_linux.go similarity index 90% rename from operator/cilium-crds/k8s/fakeresource.go rename to operator/cilium-crds/k8s/fakeresource_linux.go index c212ca61bb..c02a2286d1 100644 --- a/operator/cilium-crds/k8s/fakeresource.go +++ b/operator/cilium-crds/k8s/fakeresource_linux.go @@ -8,8 +8,7 @@ import ( "github.com/cilium/cilium/pkg/k8s/resource" ) -type fakeresource[T k8sRuntime.Object] struct { -} +type fakeresource[T k8sRuntime.Object] struct{} func (f *fakeresource[T]) Events(ctx context.Context, opts ...resource.EventsOpt) <-chan resource.Event[T] { return make(<-chan resource.Event[T]) diff --git a/operator/cilium-crds/k8s/resource_ctors.go b/operator/cilium-crds/k8s/resource_ctors.go deleted file mode 100644 index 31f61a0083..0000000000 --- a/operator/cilium-crds/k8s/resource_ctors.go +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Retina and Cilium - -// NOTE: copied and slimmed down for our use case - -package k8s - -import ( - "errors" - "fmt" - "strconv" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/tools/cache" - - cilium_api_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" - cilium_api_v2alpha1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1" - "github.com/cilium/cilium/pkg/k8s/client" - "github.com/cilium/cilium/pkg/k8s/resource" - "github.com/cilium/cilium/pkg/k8s/utils" - "github.com/cilium/hive/cell" -) - -var ErrNotACiliumEndpoint = errors.New("object is not a *cilium_api_v2.CiliumEndpoint") - -func CiliumEndpointResource(lc cell.Lifecycle, cs client.Clientset, opts ...func(*metav1.ListOptions)) (resource.Resource[*cilium_api_v2.CiliumEndpoint], error) { - if !cs.IsEnabled() { - return nil, nil - } - lw := utils.ListerWatcherWithModifiers( - utils.ListerWatcherFromTyped[*cilium_api_v2.CiliumEndpointList](cs.CiliumV2().CiliumEndpoints("")), - opts..., - ) - indexers := cache.Indexers{ - cache.NamespaceIndex: cache.MetaNamespaceIndexFunc, - CiliumEndpointIndexIdentity: identityIndexFunc, - } - return resource.New[*cilium_api_v2.CiliumEndpoint]( - lc, lw, resource.WithMetric("CiliumEndpoint"), resource.WithIndexers(indexers)), nil -} - -func identityIndexFunc(obj interface{}) ([]string, error) { - if t, ok := obj.(*cilium_api_v2.CiliumEndpoint); ok { - if t.Status.Identity != nil { - id := strconv.FormatInt(t.Status.Identity.ID, 10) - return []string{id}, nil - } - return []string{"0"}, nil - } - return nil, fmt.Errorf("%w - found %T", ErrNotACiliumEndpoint, obj) -} - -func CiliumEndpointSliceResource(lc cell.Lifecycle, cs client.Clientset, opts ...func(*metav1.ListOptions)) (resource.Resource[*cilium_api_v2alpha1.CiliumEndpointSlice], error) { - if !cs.IsEnabled() { - return nil, nil - } - lw := utils.ListerWatcherWithModifiers( - utils.ListerWatcherFromTyped[*cilium_api_v2alpha1.CiliumEndpointSliceList](cs.CiliumV2alpha1().CiliumEndpointSlices()), - opts..., - ) - return resource.New[*cilium_api_v2alpha1.CiliumEndpointSlice](lc, lw, resource.WithMetric("CiliumEndpointSlice")), nil -} diff --git a/operator/cilium-crds/k8s/resource_ctors_linux.go b/operator/cilium-crds/k8s/resource_ctors_linux.go new file mode 100644 index 0000000000..26d8913273 --- /dev/null +++ b/operator/cilium-crds/k8s/resource_ctors_linux.go @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Retina and Cilium + +package k8s + +import ( + operatork8s "github.com/cilium/cilium/operator/k8s" +) + +// Re-export Cilium's operator resource constructors. +// These live in a _linux file because cilium/operator/k8s transitively +// imports Linux-only symbols (netns.GetNetNSCookie). +var ( + CiliumEndpointResource = operatork8s.CiliumEndpointResource + CiliumEndpointSliceResource = operatork8s.CiliumEndpointSliceResource + PodResource = operatork8s.PodResource + CiliumEndpointIndexIdentity = operatork8s.CiliumEndpointIndexIdentity +) diff --git a/operator/cilium-crds/k8s/resources.go b/operator/cilium-crds/k8s/resources_linux.go similarity index 96% rename from operator/cilium-crds/k8s/resources.go rename to operator/cilium-crds/k8s/resources_linux.go index da8bc18afc..91e69422e9 100644 --- a/operator/cilium-crds/k8s/resources.go +++ b/operator/cilium-crds/k8s/resources_linux.go @@ -18,10 +18,6 @@ import ( "github.com/cilium/hive/cell" ) -const ( - CiliumEndpointIndexIdentity = "identity" -) - // ResourcesCell provides a set of handles to Kubernetes resources used throughout the // operator. Each of the resources share a client-go informer and backing store so we only // have one watch API call for each resource kind and that we maintain only one copy of each object. @@ -39,7 +35,7 @@ var ResourcesCell = cell.Module( func() resource.Resource[*cilium_api_v2.CiliumNode] { return &fakeresource[*cilium_api_v2.CiliumNode]{} }, - k8s.PodResource, + PodResource, k8s.NamespaceResource, ), ) diff --git a/operator/cmd/cilium-crds/cells_linux.go b/operator/cmd/cilium-crds/cells_linux.go index 2ddcc567d0..4339a1b8ee 100644 --- a/operator/cmd/cilium-crds/cells_linux.go +++ b/operator/cmd/cilium-crds/cells_linux.go @@ -9,17 +9,17 @@ package ciliumcrds import ( "context" "fmt" + "log/slog" "sync/atomic" "github.com/microsoft/retina/internal/buildinfo" + "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/shared/telemetry" - "github.com/sirupsen/logrus" k8sruntime "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" - zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" "github.com/microsoft/retina/operator/cilium-crds/config" operatorK8s "github.com/microsoft/retina/operator/cilium-crds/k8s" @@ -34,10 +34,12 @@ import ( cmtypes "github.com/cilium/cilium/pkg/clustermesh/types" "github.com/cilium/cilium/pkg/controller" k8sClient "github.com/cilium/cilium/pkg/k8s/client" + "github.com/cilium/cilium/pkg/kvstore" "github.com/cilium/cilium/pkg/kvstore/store" "github.com/cilium/cilium/pkg/option" "github.com/cilium/cilium/pkg/pprof" "github.com/cilium/hive/cell" + "github.com/cilium/statedb" ) const operatorK8sNamespace = "kube-system" @@ -47,7 +49,7 @@ var ( "operator", "Retina Operator", - cell.Invoke(func(l logrus.FieldLogger) { + cell.Invoke(func(l *slog.Logger) { // to help prevent user confusion, explain why logs may include lines referencing "cilium" or "cilium operator" // e.g. level=info msg="Cilium Operator go version go1.21.4 linux/amd64" subsys=retina-operator l.Info("starting hive. Some logs will say 'cilium' since some code is derived from cilium") @@ -91,6 +93,11 @@ var ( // Provides Clientset, API for accessing Kubernetes objects. k8sClient.Cell, + // Provide in-memory kvstore client for identity GC (not using etcd in Retina) + cell.Provide(func(db *statedb.DB) kvstore.Client { + return kvstore.NewInMemoryClient(db, "default") + }), + // Provides the modular metrics registry, metric HTTP server and standard metrics cell. // NOTE: no server/metrics are created when --enable-metrics=false (default) operatorMetrics.Cell, @@ -187,8 +194,8 @@ var ( // below cluster of cells carries out Retina's custom operator logic for creating Cilium Identities and Endpoints cell.Provide(func(scheme *k8sruntime.Scheme) (ctrl.Manager, error) { - // controller-runtime requires its own logger - logf.SetLogger(zapf.New()) + // Route controller-runtime logs through Retina's zap core so they reach AI. + logf.SetLogger(log.LogrLogger()) manager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, diff --git a/operator/cmd/cilium-crds/flags.go b/operator/cmd/cilium-crds/flags.go index c2d6e1482a..445ac65864 100644 --- a/operator/cmd/cilium-crds/flags.go +++ b/operator/cmd/cilium-crds/flags.go @@ -42,10 +42,6 @@ func InitGlobalFlags(cmd *cobra.Command, vp *viper.Viper) { // NOTE: without this the option gets overridden from the default value to the zero value via option.Config.Populate(vp) // specifically, here options.Config.AllocatorListTimeout gets overridden from the default value to 0s flags.Duration(option.AllocatorListTimeoutName, defaults.AllocatorListTimeout, "timeout to list initial allocator state") - // similar overriding happens for option.Config.KVstoreConnectivityTimeout - flags.Duration(option.KVstoreConnectivityTimeout, defaults.KVstoreConnectivityTimeout, "Time after which an incomplete kvstore operation is considered failed") - // similar overriding happens for option.Config.KVstorePeriodicSync - flags.Duration(option.KVstorePeriodicSync, defaults.KVstorePeriodicSync, "Periodic KVstore synchronization interval") flags.Duration(operatorOption.EndpointGCInterval, operatorOption.EndpointGCIntervalDefault, "GC interval for cilium endpoints") option.BindEnv(vp, operatorOption.EndpointGCInterval) @@ -56,7 +52,7 @@ func InitGlobalFlags(cmd *cobra.Command, vp *viper.Viper) { flags.StringSlice(option.LogDriver, []string{}, "Logging endpoints to use for example syslog") option.BindEnv(vp, option.LogDriver) - flags.Var(option.NewNamedMapOptions(option.LogOpt, &option.Config.LogOpt, nil), + flags.Var(option.NewMapOptions(&option.Config.LogOpt), option.LogOpt, `Log driver options for cilium-operator, `+ `configmap example for syslog driver: {"syslog.level":"info","syslog.facility":"local4"}`) option.BindEnv(vp, option.LogOpt) diff --git a/operator/cmd/cilium-crds/root_linux.go b/operator/cmd/cilium-crds/root_linux.go index 03e586dc19..7cbc570d5c 100644 --- a/operator/cmd/cilium-crds/root_linux.go +++ b/operator/cmd/cilium-crds/root_linux.go @@ -11,6 +11,7 @@ import ( "context" "crypto/rand" "fmt" + "log/slog" "math/big" "os" "path/filepath" @@ -19,16 +20,16 @@ import ( operatorOption "github.com/cilium/cilium/operator/option" "github.com/cilium/cilium/pkg/hive" k8sClient "github.com/cilium/cilium/pkg/k8s/client" - k8sversion "github.com/cilium/cilium/pkg/k8s/version" "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/metrics" "github.com/cilium/cilium/pkg/option" "github.com/cilium/hive/cell" "github.com/microsoft/retina/internal/buildinfo" + "github.com/microsoft/retina/pkg/log" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/viper" + "go.uber.org/zap" "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" ) @@ -36,19 +37,34 @@ import ( var ( // set logger field: subsys=retina-operator binaryName = filepath.Base(os.Args[0]) - logger = logging.DefaultLogger.WithField(logfields.LogSubsys, binaryName) + slogLoggerOnce sync.Once + cachedSlogLogger *slog.Logger operatorIDLength = 10 ) +// slogLogger returns a zap-backed slog logger. Resolved lazily so that +// SetupZapLogger (run in initEnv) is the backing source — that way every +// call here reaches Application Insights. +func slogLogger() *slog.Logger { + slogLoggerOnce.Do(func() { + cachedSlogLogger = log.SlogLogger().With(logfields.LogSubsys, binaryName) + }) + return cachedSlogLogger +} + func Execute(h *hive.Hive) { initEnv(h.Viper()) - if err := h.Run(logging.DefaultSlogLogger); err != nil { - logger.Fatal(err) + // Use zap-backed slog logger for hive (routes to stdout + Application Insights) + if err := h.Run(log.SlogLogger()); err != nil { + logging.Fatal(slogLogger(), err.Error()) } } -func registerOperatorHooks(l logrus.FieldLogger, lc cell.Lifecycle, llc *LeaderLifecycle, clientset k8sClient.Clientset, shutdowner hive.Shutdowner) { +func registerOperatorHooks( + l *slog.Logger, lc cell.Lifecycle, llc *LeaderLifecycle, + clientset k8sClient.Clientset, shutdowner hive.Shutdowner, +) { var wg sync.WaitGroup lc.Append(cell.Hook{ OnStart: func(cell.HookContext) error { @@ -77,19 +93,34 @@ func initEnv(vp *viper.Viper) { // the default values provided in option.Config or operatorOption.Config respectively. // The values will be overridden to the "zero value". // Maybe could create a cell.Config for these instead? - option.Config.Populate(vp) - operatorOption.Config.Populate(vp) - - // add hooks after setting up metrics in the option.Confog - logging.DefaultLogger.Hooks.Add(metrics.NewLoggingHook()) + // slogloggercheck: using default logger for configuration initialization + option.Config.Populate(logging.DefaultSlogLogger, vp) + operatorOption.Config.Populate(logging.DefaultSlogLogger, vp) + + // Bring up Retina's zap logger (stdout + Application Insights). We redirect + // Go's stdlib slog default at it now; the Cilium-side tee has to wait until + // after logging.SetupLogging runs, because SetupLogging calls + // defaultMultiSlogHandler.SetHandler, which replaces all registered + // handlers. + _, _ = log.SetupZapLogger(&log.LogOpts{ + Level: option.Config.LogOpt[logging.LevelOpt], + ApplicationInsightsID: buildinfo.ApplicationInsightsID, + EnableTelemetry: buildinfo.ApplicationInsightsID != "", + }, zap.String("version", buildinfo.Version)) + log.SetDefaultSlog() // Logging should always be bootstrapped first. Do not add any code above this! if err := logging.SetupLogging(option.Config.LogDriver, logging.LogOptions(option.Config.LogOpt), binaryName, option.Config.Debug); err != nil { - logger.Fatal(err) + logging.Fatal(slogLogger(), err.Error()) } - option.LogRegisteredOptions(vp, logger) - logger.Infof("retina operator version: %s", buildinfo.Version) + // Register zap + metrics hook AFTER SetupLogging so they survive the + // MultiSlogHandler replace. From here on every logging.DefaultSlogLogger + // emission fans out to zap → Application Insights. + logging.AddHandlers(log.SlogHandler(), metrics.NewLoggingHook()) + + option.LogRegisteredSlogOptions(vp, slogLogger()) + slogLogger().Info("retina operator version", "version", buildinfo.Version) } func doCleanup() { @@ -103,32 +134,20 @@ func doCleanup() { // runOperator implements the logic of leader election for cilium-operator using // built-in leader election capability in kubernetes. // See: https://github.com/kubernetes/client-go/blob/master/examples/leader-election/main.go -func runOperator(l logrus.FieldLogger, lc *LeaderLifecycle, clientset k8sClient.Clientset, shutdowner hive.Shutdowner) { +func runOperator(l *slog.Logger, lc *LeaderLifecycle, clientset k8sClient.Clientset, shutdowner hive.Shutdowner) { isLeader.Store(false) leaderElectionCtx, leaderElectionCtxCancel = context.WithCancel(context.Background()) - // We only support Operator in HA mode for Kubernetes Versions having support for - // LeasesResourceLock. - // See docs on capabilities.LeasesResourceLock for more context. - if !k8sversion.Capabilities().LeasesResourceLock { - l.Info("Support for coordination.k8s.io/v1 not present, fallback to non HA mode") - - if err := lc.Start(logging.DefaultSlogLogger, leaderElectionCtx); err != nil { - l.WithError(err).Fatal("Failed to start leading") - } - return - } - // Get hostname for identity name of the lease lock holder. // We identify the leader of the operator cluster using hostname. operatorID, err := os.Hostname() if err != nil { - l.WithError(err).Fatal("Failed to get hostname when generating lease lock identity") + logging.Fatal(l, "Failed to get hostname when generating lease lock identity", logfields.Error, err) } operatorID, err = randomStringWithPrefix(operatorID+"-", operatorIDLength) if err != nil { - l.WithError(err).Fatal("Failed to generate random string for lease lock identity") + logging.Fatal(l, "Failed to generate random string for lease lock identity", logfields.Error, err) } leResourceLock, err := resourcelock.NewFromKubeconfig( @@ -142,7 +161,7 @@ func runOperator(l logrus.FieldLogger, lc *LeaderLifecycle, clientset k8sClient. clientset.RestConfig(), operatorOption.Config.LeaderElectionRenewDeadline) if err != nil { - l.WithError(err).Fatal("Failed to create resource lock for leader election") + logging.Fatal(l, "Failed to create resource lock for leader election", logfields.Error, err) } // Start the leader election for running cilium-operators @@ -160,12 +179,12 @@ func runOperator(l logrus.FieldLogger, lc *LeaderLifecycle, clientset k8sClient. Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: func(ctx context.Context) { if err := lc.Start(logging.DefaultSlogLogger, ctx); err != nil { - l.WithError(err).Error("Failed to start when elected leader, shutting down") + l.Error("Failed to start when elected leader, shutting down", logfields.Error, err) shutdowner.Shutdown(hive.ShutdownWithError(err)) } }, OnStoppedLeading: func() { - l.WithField("operator-id", operatorID).Info("Leader election lost") + l.Info("Leader election lost", "operator-id", operatorID) // Cleanup everything here, and exit. shutdowner.Shutdown(hive.ShutdownWithError(errors.New("Leader election lost"))) }, @@ -173,10 +192,7 @@ func runOperator(l logrus.FieldLogger, lc *LeaderLifecycle, clientset k8sClient. if identity == operatorID { l.Info("Leading the operator HA deployment") } else { - l.WithFields(logrus.Fields{ - "newLeader": identity, - "operatorID": operatorID, - }).Info("Leader re-election complete") + l.Info("Leader re-election complete", "newLeader", identity, "operatorID", operatorID) } }, }, diff --git a/operator/cmd/cilium-crds/zap_linux.go b/operator/cmd/cilium-crds/zap_linux.go index 8853180250..75edc9cbe1 100644 --- a/operator/cmd/cilium-crds/zap_linux.go +++ b/operator/cmd/cilium-crds/zap_linux.go @@ -4,85 +4,34 @@ package ciliumcrds import ( - "fmt" - "io" + "log/slog" - zaphook "github.com/Sytten/logrus-zap-hook" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/option" "github.com/cilium/hive/cell" "github.com/microsoft/retina/internal/buildinfo" "github.com/microsoft/retina/pkg/log" - "github.com/sirupsen/logrus" "go.uber.org/zap" "k8s.io/client-go/rest" "github.com/microsoft/retina/operator/cilium-crds/config" ) -// TODO refactor to another package? Like shared/telemetry/ - -const logFileName = "retina-operator.log" - -var ( - MaxFileSizeMB = 100 - MaxBackups = 3 - MaxAgeDays = 30 -) - type params struct { cell.In - Logger logrus.FieldLogger + Logger *slog.Logger K8sCfg *rest.Config DaemonCfg *option.DaemonConfig OperatorCfg config.Config } func setupZapHook(p params) { - // modify default logger - // properly report the caller (otherwise, will get caller=zap.go every time) - logging.DefaultLogger.ReportCaller = true - // discard default logger output in favor of zap - logging.DefaultLogger.SetOutput(io.Discard) - - level, err := logrus.ParseLevel(p.DaemonCfg.LogOpt[logging.LevelOpt]) - if err != nil { - p.Logger.WithError(err).Error("failed to parse log level") - } else { - logging.DefaultLogger.SetLevel(level) - } - - lOpts := &log.LogOpts{ - Level: p.DaemonCfg.LogOpt[logging.LevelOpt], - File: false, - FileName: logFileName, - MaxFileSizeMB: MaxFileSizeMB, - MaxBackups: MaxBackups, - MaxAgeDays: MaxAgeDays, - ApplicationInsightsID: buildinfo.ApplicationInsightsID, - EnableTelemetry: p.OperatorCfg.EnableTelemetry, - } - - persistentFields := []zap.Field{ + // Note: Zap logger is now initialized in initEnv() before hive starts. + // This hook only logs startup info with operator-specific fields from the hive DI context. + namedLogger := log.Logger().Named("retina-operator-v2") + namedLogger.Info("Traces telemetry initialized with zapai", zap.String("version", buildinfo.Version), + zap.String("appInsightsID", buildinfo.ApplicationInsightsID), zap.String("apiserver", p.K8sCfg.Host), - } - - _, err = log.SetupZapLogger(lOpts, persistentFields...) - if err != nil { - fmt.Printf("failed to setup zap logger: %v", err) - } - - namedLogger := log.Logger().Named("retina-operator-v2") - namedLogger.Info("Traces telemetry initialized with zapai", zap.String("version", buildinfo.Version), zap.String("appInsightsID", lOpts.ApplicationInsightsID)) - - var hook *zaphook.ZapHook - hook, err = zaphook.NewZapHook(namedLogger.Logger) - if err != nil { - p.Logger.WithError(err).Error("failed to create zap hook") - return - } - - logging.DefaultLogger.Hooks.Add(hook) + ) } diff --git a/operator/cmd/cilium_crds_cmd_linux.go b/operator/cmd/cilium_crds_cmd_linux.go index 701be12166..f59e189c9e 100644 --- a/operator/cmd/cilium_crds_cmd_linux.go +++ b/operator/cmd/cilium_crds_cmd_linux.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/cilium/cilium/pkg/hive" + "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/option" ciliumcrds "github.com/microsoft/retina/operator/cmd/cilium-crds" "github.com/spf13/cobra" @@ -40,7 +41,7 @@ func init() { } cobra.OnInitialize( - option.InitConfig(cmd, "Retina-Operator", "retina-operators", h.Viper()), + option.InitConfig(logging.DefaultSlogLogger, cmd, "Retina-Operator", "retina-operators", h.Viper()), ) rootCmd.AddCommand(cmd) diff --git a/operator/cmd/standard/deployment.go b/operator/cmd/standard/deployment.go index d47509b021..41a7469d57 100644 --- a/operator/cmd/standard/deployment.go +++ b/operator/cmd/standard/deployment.go @@ -9,11 +9,10 @@ import ( "net/http" "net/http/pprof" - "go.uber.org/zap/zapcore" - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. + "github.com/cilium/cilium/pkg/logging" "go.uber.org/zap" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1" @@ -23,7 +22,6 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" - crzap "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" @@ -98,6 +96,10 @@ func (o *Operator) Start() error { } defer zl.Close() + // Tee Cilium's MultiSlogHandler into zap so any DefaultSlogLogger call + // (including package-var captures) reaches Application Insights. + logging.AddHandlers(log.SlogHandler()) + log.SetDefaultSlog() // Set Go's global slog to use zap-backed handler mainLogger := zl.Named("main").Sugar() mainLogger.Info("Operator configuration", zap.Any("configuration", oconfig)) @@ -106,11 +108,8 @@ func (o *Operator) Start() error { oconfig.CaptureConfig.CaptureImageVersion = buildinfo.Version oconfig.CaptureConfig.CaptureImageVersionSource = captureUtils.VersionSourceOperatorImageVersion - opts := &crzap.Options{ - Development: false, - } - - ctrl.SetLogger(crzap.New(crzap.UseFlagOptions(opts), crzap.Encoder(zapcore.NewConsoleEncoder(log.EncoderConfig())))) + // Route controller-runtime logs through Retina's zap core so they also reach AI. + ctrl.SetLogger(log.LogrLogger()) mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, diff --git a/pkg/common/endpoint.go b/pkg/common/endpoint.go index d4f775b1f1..9df09aff7e 100644 --- a/pkg/common/endpoint.go +++ b/pkg/common/endpoint.go @@ -165,7 +165,7 @@ func (ep *RetinaEndpoint) PrimaryIP() (string, error) { } } - return "", errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, "%s", ep.Key()) + return "", errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, "endpoint: %s", ep.Key()) } func (ep *RetinaEndpoint) PrimaryNetIP() (net.IP, error) { @@ -179,7 +179,7 @@ func (ep *RetinaEndpoint) PrimaryNetIP() (net.IP, error) { } } - return nil, errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, "%s", ep.Key()) + return nil, errors.Wrapf(ErrNoPrimaryIPFoundEndpoint, "endpoint: %s", ep.Key()) } func (ep *RetinaEndpoint) NodeIP() string { diff --git a/pkg/config/hubble_config_linux.go b/pkg/config/hubble_config_linux.go index 3f24742459..1f24712b71 100644 --- a/pkg/config/hubble_config_linux.go +++ b/pkg/config/hubble_config_linux.go @@ -3,12 +3,12 @@ package config import ( + "log/slog" "path/filepath" "github.com/cilium/cilium/pkg/option" "github.com/cilium/hive/cell" sharedconfig "github.com/microsoft/retina/pkg/shared/config" - "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) @@ -64,14 +64,14 @@ var ( cell.Config(DefaultRetinaHubbleConfig), - cell.Provide(func(logger logrus.FieldLogger) (Config, error) { + cell.Provide(func(logger *slog.Logger) (Config, error) { retinaConfigFile := filepath.Join(option.Config.ConfigDir, configFileName) conf, err := GetConfig(retinaConfigFile) if err != nil { - logger.Error(err) + logger.Error("failed to get config", "error", err) conf = DefaultRetinaConfig } - logger.Info(conf) + logger.Info("loaded config", "config", conf) return *conf, nil }), sharedconfig.Cell, diff --git a/pkg/controllers/daemon/nodereconciler/cell_linux.go b/pkg/controllers/daemon/nodereconciler/cell_linux.go index b7fd1f47ef..222a6d9d16 100644 --- a/pkg/controllers/daemon/nodereconciler/cell_linux.go +++ b/pkg/controllers/daemon/nodereconciler/cell_linux.go @@ -1,6 +1,7 @@ package nodereconciler import ( + "log/slog" "os" datapath "github.com/cilium/cilium/pkg/datapath/types" @@ -10,7 +11,6 @@ import ( "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/log" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -20,10 +20,10 @@ var Cell = cell.Module( "Node Controller monitors Node CRUD events", cell.Provide(newNodeController), // Setting up the node controller with the controller manager - cell.Invoke(func(l logrus.FieldLogger, nr *NodeReconciler, ctrlManager ctrl.Manager) error { + cell.Invoke(func(l *slog.Logger, nr *NodeReconciler, ctrlManager ctrl.Manager) error { l.Info("Setting up node controller with manager") if err := nr.SetupWithManager(ctrlManager); err != nil { - l.Errorf("failed to setup node controller with manager: %v", err) + l.Error("failed to setup node controller with manager", "error", err) return errors.Wrap(err, "failed to setup node controller with manager") } return nil diff --git a/pkg/controllers/daemon/nodereconciler/node_controller_linux.go b/pkg/controllers/daemon/nodereconciler/node_controller_linux.go index 70df453010..bcbb903bfd 100644 --- a/pkg/controllers/daemon/nodereconciler/node_controller_linux.go +++ b/pkg/controllers/daemon/nodereconciler/node_controller_linux.go @@ -246,8 +246,6 @@ func (r *NodeReconciler) ClusterSizeDependantInterval(time.Duration) time.Durati return time.Second * 5 } -func (r *NodeReconciler) Enqueue(*types.Node) {} - func (r *NodeReconciler) GetNodeIdentities() []types.Identity { return []types.Identity{} } @@ -264,10 +262,6 @@ func (r *NodeReconciler) NodeSync() {} func (r *NodeReconciler) NodeUpdated(types.Node) {} -func (r *NodeReconciler) StartNeighborRefresh(datapath.NodeNeighbors) {} - -func (r *NodeReconciler) StartNodeNeighborLinkUpdater(datapath.NodeNeighbors) {} - func (r *NodeReconciler) SetPrefixClusterMutatorFn(func(*types.Node) []cmtypes.PrefixClusterOpts) {} // extractNodeIPs extracts IP addresses from a node diff --git a/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux.go b/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux.go index 4be4c84ddd..019079bb09 100644 --- a/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux.go +++ b/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux.go @@ -14,8 +14,6 @@ import ( "github.com/microsoft/retina/pkg/controllers/operator/cilium-crds/cache" "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "go.uber.org/zap" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -30,6 +28,7 @@ import ( "github.com/cilium/cilium/pkg/labels" "github.com/cilium/hive/cell" "github.com/cilium/workerpool" + retinalog "github.com/microsoft/retina/pkg/log" ) const ( @@ -47,7 +46,7 @@ var ErrClientsetDisabled = errors.New("failure due to clientset disabled") // endpointReconciler managed the lifecycle of CiliumEndpoints and CiliumIdentities from Pods. type endpointReconciler struct { *sync.Mutex - l logrus.FieldLogger + l *slog.Logger clientset versioned.Interface ciliumSlimClientSet slim_clientset.Interface // podEvents represents Pod CRUD events relayed from the Pod controller. If the Pod was deleted, the PodCacheObject.Pod field will be nil @@ -76,7 +75,6 @@ type endpointReconciler struct { type params struct { cell.In - Logger logrus.FieldLogger Lifecycle cell.Lifecycle Clientset k8sClient.Clientset CiliumEndpoints resource.Resource[*ciliumv2.CiliumEndpoint] @@ -89,7 +87,7 @@ func registerEndpointController(p params) error { return ErrClientsetDisabled } - l := p.Logger.WithField("component", "endpointcontroller") + l := retinalog.SlogLogger().With("component", "endpointcontroller") r := &endpointReconciler{ Mutex: &sync.Mutex{}, l: l, @@ -106,10 +104,10 @@ func registerEndpointController(p params) error { return nil } -func (r *endpointReconciler) Start(_ cell.HookContext) error { +func (r *endpointReconciler) Start(ctx cell.HookContext) error { // NOTE: we must create IdentityManager on leader election since its allocator auto-starts on creation. // There is a way to disable auto-start but then there is no exposed function to simply start(). - im, err := NewIdentityManager(r.l, r.clientset) + im, err := NewIdentityManager(ctx, r.l, r.clientset) if err != nil { return errors.Wrap(err, "failed to create identity manager") } @@ -152,7 +150,7 @@ func (r *endpointReconciler) run(pctx context.Context) error { } if ev.Object != nil && ev.Object.Spec.HostNetwork { - r.l.WithField("podKey", ev.Key.String()).Debug("pod is host networked, skipping") + r.l.Debug("pod is host networked, skipping", "podKey", ev.Key.String()) ev.Done(nil) continue } @@ -161,7 +159,7 @@ func (r *endpointReconciler) run(pctx context.Context) error { return r.runEventHandler(ctx, ev) }) if err != nil { - r.l.WithError(err).WithField("podKey", ev.Key.String()).Error("failed to submit pod event handler") + r.l.Error("failed to submit pod event handler", "error", err, "podKey", ev.Key.String()) } case <-pctx.Done(): @@ -180,7 +178,7 @@ func (r *endpointReconciler) runEventHandler(pctx context.Context, ev resource.E case resource.Upsert: // HANDLE UPSERT if ev.Object != nil && ev.Object.Spec.HostNetwork { - r.l.WithField("podKey", ev.Key.String()).Debug("pod is host networked, skipping") + r.l.Debug("pod is host networked, skipping", "podKey", ev.Key.String()) } else { err = r.ReconcilePod(ctx, ev.Key, ev.Object) } @@ -190,7 +188,7 @@ func (r *endpointReconciler) runEventHandler(pctx context.Context, ev resource.E cancel() if err != nil { - r.l.WithError(err).WithField("podKey", ev.Key.String()).Error("error creating cilium endpoint. requeuing pod") + r.l.Error("error creating cilium endpoint. requeuing pod", "error", err, "podKey", ev.Key.String()) } ev.Done(err) @@ -224,7 +222,7 @@ func (r *endpointReconciler) runNamespaceEvents(pctx context.Context) error { cancel() if err != nil { - r.l.WithError(err).WithField("namespaceKey", ev.Key.String()).Error("error creating cilium endpoint. requeuing namespace") + r.l.Error("error creating cilium endpoint. requeuing namespace", "error", err, "namespaceKey", ev.Key.String()) } ev.Done(err) case <-pctx.Done(): @@ -237,17 +235,17 @@ func (r *endpointReconciler) runNamespaceEvents(pctx context.Context) error { func (r *endpointReconciler) ReconcilePodsInNamespace(ctx context.Context, namespace string) error { r.Mutex.Lock() defer r.Mutex.Unlock() - r.l.Debug("reconciling pods in namespace", zap.String("namespace ", namespace)) + r.l.Debug("reconciling pods in namespace", "namespace", namespace) podList := r.store.ListPodKeysByNamespace(namespace) for _, podKey := range podList { pod, ok := r.store.GetPod(podKey) if !ok { - r.l.WithField("podKey", podKey.String()).Debug("pod not found in cache, skipping") + r.l.Debug("pod not found in cache, skipping", "podKey", podKey.String()) continue } if pod.toDelete { - r.l.WithField("podKey", podKey.String()).Debug("pod marked for deletion, skipping") + r.l.Debug("pod marked for deletion, skipping", "podKey", podKey.String()) continue } @@ -259,17 +257,16 @@ func (r *endpointReconciler) ReconcilePodsInNamespace(ctx context.Context, names newPEP.lbls = endpointsLabels r.l.Debug("upserting pod in namespace", - zap.String("namespace ", namespace), - zap.String("podKey", podKey.String()), - zap.Any("old labels ", pod.lbls), - zap.Any("new labels ", newPEP.lbls), + "namespace", namespace, + "podKey", podKey.String(), + "old labels", pod.lbls, + "new labels", newPEP.lbls, ) err = r.handlePodUpsert(ctx, newPEP) if err != nil { - r.l.Error("failed to upsert pod", zap.Error(err), zap.String("podKey", podKey.String())) + r.l.Error("failed to upsert pod", "error", err, "podKey", podKey.String()) } - if err != nil { return errors.Wrap(err, "failed to upsert pod") } @@ -282,7 +279,7 @@ func (r *endpointReconciler) ReconcilePodsInNamespace(ctx context.Context, names func (r *endpointReconciler) ReconcilePod(ctx context.Context, podKey resource.Key, pod *slim_corev1.Pod) error { r.Mutex.Lock() defer r.Mutex.Unlock() - r.l.Debug("reconciling pod with lock", zap.String("namespace", podKey.Namespace), zap.String("pod ", podKey.Name)) + r.l.Debug("reconciling pod with lock", "namespace", podKey.Namespace, "pod", podKey.Name) return r.reconcilePod(ctx, podKey, pod) } @@ -297,7 +294,7 @@ func (r *endpointReconciler) reconcilePod(ctx context.Context, podKey resource.K } if pod.Status.PodIP == "" || pod.Status.HostIP == "" { - r.l.WithField("podKey", podKey.String()).Trace("pod missing an IP, skipping") + r.l.Debug("pod missing an IP, skipping", "podKey", podKey.String()) return nil } @@ -326,7 +323,7 @@ func (r *endpointReconciler) reconcilePod(ctx context.Context, podKey resource.K func (r *endpointReconciler) HandlePodDelete(ctx context.Context, n resource.Key) error { r.Mutex.Lock() defer r.Mutex.Unlock() - r.l.Debug("handling pod delete with lock", zap.String("podKey", n.String())) + r.l.Debug("handling pod delete with lock", "podKey", n.String()) return r.handlePodDelete(ctx, n) } @@ -335,20 +332,20 @@ func (r *endpointReconciler) handlePodDelete(ctx context.Context, n resource.Key if !ok { // do not do anything if we have not processed the pod // let endpointgc delete the CiliumEndpoint as necessary - r.l.WithField("podKey", n.String()).Trace("pod not found in cache, skipping deletion") + r.l.Debug("pod not found in cache, skipping deletion", "podKey", n.String()) return nil } - r.l.WithField("podKey", n.String()).Trace("handling pod delete") + r.l.Debug("handling pod delete", "podKey", n.String()) // delete CEP even if we haven't processed the Pod (and incremented identity reference count) err := r.clientset.CiliumV2().CiliumEndpoints(n.Namespace).Delete(ctx, n.Name, metav1.DeleteOptions{}) if err != nil && !k8serrors.IsNotFound(err) { - r.l.WithError(err).WithField("podKey", n.String()).Error("failed to delete CiliumEndpoint") + r.l.Error("failed to delete CiliumEndpoint", "error", err, "podKey", n.String()) return errors.Wrap(err, "failed to delete endpoint") } - r.l.WithField("podKey", n.String()).Debug("deleted CiliumEndpoint") + r.l.Debug("deleted CiliumEndpoint", "podKey", n.String()) // Identity reference count must be modified after CiliumEndpoint is successfully deleted. // Otherwise, we could decrement reference multiple times if CiliumEndpoint deletion fails and we retry this method. @@ -359,15 +356,15 @@ func (r *endpointReconciler) handlePodDelete(ctx context.Context, n resource.Key } func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEndpoint) error { //nolint:gocyclo // This function is too complex and should be refactored - r.l.WithField("podKey", newPEP.key.String()).Trace("handling pod upsert") + r.l.Debug("handling pod upsert", "podKey", newPEP.key.String()) oldPEP, inCache := r.store.GetPod(newPEP.key) inStore := false if inCache { - r.l.WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "pep": oldPEP, - }).Trace("PodEndpoint found in cache") + r.l.Debug("PodEndpoint found in cache", + "podKey", newPEP.key.String(), + "pep", oldPEP, + ) } else { // this call will block until the store is synced with API Server store, err := r.ciliumEndpoints.Store(ctx) @@ -384,21 +381,21 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd inStore = ok if inStore { - r.l.WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "ownerReferences": oldCEP.ObjectMeta.OwnerReferences, - "endpointID": oldCEP.Status.ID, - "identity": oldCEP.Status.Identity, - "networking": oldCEP.Status.Networking, - }).Trace("CiliumEndpoint found in store") + r.l.Debug("CiliumEndpoint found in store", + "podKey", newPEP.key.String(), + "ownerReferences", oldCEP.OwnerReferences, + "endpointID", oldCEP.Status.ID, + "identity", oldCEP.Status.Identity, + "networking", oldCEP.Status.Networking, + ) if oldCEP.Status.Networking == nil || len(oldCEP.Status.Networking.Addressing) == 0 || oldCEP.Status.Networking.Addressing[0].IPV4 == "" { // FIXME handle IPv6 and dual-stack inStore = false - r.l.WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "cep": oldCEP, - }).Warn("CiliumEndpoint has no ipv4 address, ignoring") + r.l.Warn("CiliumEndpoint has no ipv4 address, ignoring", + "podKey", newPEP.key.String(), + "cep", oldCEP, + ) } else { oldPEP = &PodEndpoint{ key: newPEP.key, @@ -424,23 +421,23 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd sameNetworking := newPEP.ipv4 == oldPEP.ipv4 && newPEP.nodeIP == oldPEP.nodeIP equalLabels := newPEP.lbls.Equals(oldPEP.lbls) - r.l.WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "inCache": inCache, - "sameNetworking": sameNetworking, - "equalLabels": equalLabels, - "oldLbls": oldPEP.lbls, - "newLbls": newPEP.lbls, - }).Trace("patching CiliumEndpoint") + r.l.Debug("patching CiliumEndpoint", + "podKey", newPEP.key.String(), + "inCache", inCache, + "sameNetworking", sameNetworking, + "equalLabels", equalLabels, + "oldLbls", oldPEP.lbls, + "newLbls", newPEP.lbls, + ) // allocate new identity if labels have changed or if we haven't assigned an identity ID to this pod yet // TODO when implementing follower check if inCache or processedAsLeader shouldAllocateNewIdentity := !inCache || !equalLabels || newPEP.identityID == 0 if shouldAllocateNewIdentity { - r.l.WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "pep": oldPEP, - }).Trace("creating new identity for pod") + r.l.Debug("creating new identity for pod", + "podKey", newPEP.key.String(), + "pep", oldPEP, + ) identityID, err := r.identityManager.GetIdentityAndIncrementReference(ctx, newPEP.lbls) if err != nil { @@ -452,13 +449,13 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd if sameNetworking && equalLabels { // nothing to do. pod already has a CEP with the same networking and labels - r.l.WithField("podKey", newPEP.key.String()).Trace("pod already processed") + r.l.Debug("pod already processed", "podKey", newPEP.key.String()) r.store.AddPod(newPEP) return nil } if !sameNetworking { - r.l.WithField("podKey", newPEP.key.String()).Trace("pod networking has changed") + r.l.Debug("pod networking has changed", "podKey", newPEP.key.String()) // change endpoint id since networking has changed // FIXME use endpoint allocator to get new endpoint ID newPEP.endpointID++ @@ -493,15 +490,15 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd createStatusPatch, err := json.Marshal(replaceCEPStatus) if err != nil { - r.l.WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "pep": newPEP, - "uid": newPEP.uid, - }).Debug("marshalling status failed") + r.l.Debug("marshalling status failed", + "podKey", newPEP.key.String(), + "pep", newPEP, + "uid", newPEP.uid, + ) if shouldAllocateNewIdentity { // decrement reference for new identity - r.l.WithField("podKey", newPEP.key.String()).Trace("marshal failed, decrementing reference for new identity") + r.l.Debug("marshal failed, decrementing reference for new identity", "podKey", newPEP.key.String()) r.identityManager.DecrementReference(ctx, newPEP.lbls) } @@ -526,7 +523,7 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd // Decrement reference for new identity. // May end up incrementing reference count for this same identity again if we try to create the CEP below. // No downside to decrementing reference here and then incrementing again below (will not affect API Server). - r.l.WithField("podKey", newPEP.key.String()).Trace("patch unsuccessful, decrementing reference for new identity") + r.l.Debug("patch unsuccessful, decrementing reference for new identity", "podKey", newPEP.key.String()) r.identityManager.DecrementReference(ctx, newPEP.lbls) } @@ -535,16 +532,18 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd // No downside to this. if !k8serrors.IsNotFound(err) { - r.l.WithError(err).WithFields(logrus.Fields{ - "podKey": newPEP.key.String(), - "pep": newPEP, - "uid": newPEP.uid, - }).Error("failed to patch CiliumEndpoint") + r.l.Error("failed to patch CiliumEndpoint", + "error", err, + "podKey", newPEP.key.String(), + "pep", newPEP, + "uid", newPEP.uid, + ) return errors.Wrap(err, "failed to patch endpoint") } - r.l.WithField("podKey", newPEP.key.String()).Debug("patch unsuccessful because CiliumEndpoint is not in API Server. now creating CiliumEndpoint") + r.l.Debug("patch unsuccessful because CiliumEndpoint is not in API Server. now creating CiliumEndpoint", + "podKey", newPEP.key.String()) // Endpoint was not found, create it below. // Make sure the pod does not exist in the cache so that we don't try to patch it again (in case of a retry after a failure below). @@ -585,13 +584,13 @@ func (r *endpointReconciler) handlePodUpsert(ctx context.Context, newPEP *PodEnd _, err = r.clientset.CiliumV2().CiliumEndpoints(newPEP.key.Namespace).Create(ctx, newCEP, metav1.CreateOptions{}) if err != nil { - r.l.WithError(err).WithField("podKey", newPEP.key.String()).Error("failed to create CiliumEndpoint") + r.l.Error("failed to create CiliumEndpoint", "error", err, "podKey", newPEP.key.String()) r.identityManager.DecrementReference(ctx, newPEP.lbls) // FIXME release newly allocated endpoint ID return errors.Wrap(err, "failed to create endpoint") } - r.l.WithField("podKey", newPEP.key.String()).Debug("created CiliumEndpoint") + r.l.Debug("created CiliumEndpoint", "podKey", newPEP.key.String()) r.store.AddPod(newPEP) return nil } @@ -609,7 +608,7 @@ func (r *endpointReconciler) reconcileNamespace(ctx context.Context, namespace * // check if namespace is in cache oldNs, ok := r.store.GetNamespace(namespace.GetName()) if !ok { - r.l.Debug("Adding new namespace to cache", zap.String("namespace ", namespace.GetName())) + r.l.Debug("Adding new namespace to cache", "namespace", namespace.GetName()) // if this is the first time we see this namespace, add it to cache // there might not be any pods in this namespace yet r.store.AddNamespace(namespace) @@ -617,16 +616,16 @@ func (r *endpointReconciler) reconcileNamespace(ctx context.Context, namespace * } if oldNs.GetResourceVersion() == namespace.GetResourceVersion() { - r.l.Debug("Namespace already processed", zap.String("namespace ", namespace.GetName())) + r.l.Debug("Namespace already processed", "namespace", namespace.GetName()) return nil } if reflect.DeepEqual(oldNs.Labels, namespace.Labels) { - r.l.Debug("Namespace labels are the same", zap.String("namespace ", namespace.GetName())) + r.l.Debug("Namespace labels are the same", "namespace", namespace.GetName()) return nil } - r.l.Debug("Updating namespace in cache", zap.String("namespace ", namespace.GetName())) + r.l.Debug("Updating namespace in cache", "namespace", namespace.GetName()) r.store.AddNamespace(namespace) // now get all pods and update them as well @@ -640,11 +639,11 @@ func (r *endpointReconciler) reconcileNamespace(ctx context.Context, namespace * func (r *endpointReconciler) handleNamespaceDelete(_ context.Context, namespaceName string) error { _, ok := r.store.GetNamespace(namespaceName) if !ok { - r.l.Debug("Adding new namespace to cache", zap.String("namespace ", namespaceName)) + r.l.Debug("Adding new namespace to cache", "namespace", namespaceName) return nil } - r.l.Debug("Deleting namespace from cache", zap.String("namespace ", namespaceName)) + r.l.Debug("Deleting namespace from cache", "namespace", namespaceName) // Ignore deleting the pods for this NS, pod controller will eventually clean it up. // Once deleting all the pods in the namespace, delete the namespace r.store.DeleteNamespace(namespaceName) @@ -658,20 +657,22 @@ func (r *endpointReconciler) ciliumEndpointsLabels(ctx context.Context, pod *sli if !ok { ns, err = r.ciliumSlimClientSet.CoreV1().Namespaces().Get(ctx, pod.Namespace, metav1.GetOptions{}) if err != nil { - r.l.WithError(err).WithFields(logrus.Fields{ - "podKey": pod.Name, - "ns": pod.Namespace, - }).Error("failed to get namespace") + r.l.Error("failed to get namespace", + "error", err, + "podKey", pod.Name, + "ns", pod.Namespace, + ) return nil, errors.Wrap(err, "failed to get namespace") } r.store.AddNamespace(ns) } _, ciliumLabels := k8s.GetPodMetadata(slog.Default(), ns, pod) if err != nil { - r.l.WithError(err).WithFields(logrus.Fields{ - "podKey": pod.Name, - "ns": pod.Namespace, - }).Error("failed to get pod metadata") + r.l.Error("failed to get pod metadata", + "error", err, + "podKey", pod.Name, + "ns", pod.Namespace, + ) return nil, errors.Wrap(err, "failed to get pod metadata") } lbls := make(labels.Labels, len(ciliumLabels)) diff --git a/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux_test.go b/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux_test.go index 1ac913d1ea..74bad2fc6d 100644 --- a/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux_test.go +++ b/pkg/controllers/operator/cilium-crds/endpoint/endpoint_controller_linux_test.go @@ -9,7 +9,7 @@ import ( "time" ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" - ciliumclient "github.com/cilium/cilium/pkg/k8s/client" + ciliumclient "github.com/cilium/cilium/pkg/k8s/client/testutils" "github.com/cilium/cilium/pkg/k8s/resource" v1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" @@ -18,7 +18,6 @@ import ( "github.com/cilium/cilium/pkg/option" "github.com/microsoft/retina/pkg/controllers/operator/cilium-crds/cache" ciliumutil "github.com/microsoft/retina/pkg/utils/testutil/cilium" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -667,8 +666,7 @@ func TestSortedLabels(t *testing.T) { func newTestEndpointReconciler(t *testing.T) (*endpointReconciler, *ciliumutil.MockResource[*ciliumv2.CiliumEndpoint]) { t.Helper() - l := logrus.New() - l.SetLevel(logrus.DebugLevel) + l := slog.Default() ciliumEndpoints := ciliumutil.NewMockResource[*ciliumv2.CiliumEndpoint](l) fakeClientSet, _ := ciliumclient.NewFakeClientset(slog.Default()) @@ -686,7 +684,8 @@ func newTestEndpointReconciler(t *testing.T) (*endpointReconciler, *ciliumutil.M // make sure to use CRD mode (this is referenced in InitIdentityAllocator) option.Config.IdentityAllocationMode = option.IdentityAllocationModeCRD - im, err := NewIdentityManager(l, m) + // Use the Cilium fake clientset for identity manager since it has proper watch support + im, err := NewIdentityManager(context.Background(), l, fakeClientSet.CiliumFakeClientset) require.NoError(t, err) r.identityManager = im diff --git a/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux.go b/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux.go index 2a2b5461ab..831034be30 100644 --- a/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux.go +++ b/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux.go @@ -2,23 +2,26 @@ package endpointcontroller import ( "context" + "log/slog" + "time" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/identity" "github.com/cilium/cilium/pkg/identity/cache" "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned" "github.com/cilium/cilium/pkg/labels" - "github.com/cilium/cilium/pkg/option" ) +// Default timeout for identity allocation operations +const identityAllocatorTimeout = 2 * time.Minute + // IdentityManager is analogous to Cilium Daemon's identity allocation. // Cilium has an IPCacche holding IP to Identity mapping. // In IPCache.InjectLabels(), IPCacche is told of IPs which have been updated. // Within this function, identities are allocated/released via CachingIdentityAllocator. type IdentityManager struct { - l logrus.FieldLogger + l *slog.Logger // alloc is the CachingIdentityAllocator which helps in: // - allocating/releasing identities (maintaining reference counts and creating CRDs) // - syncing identity "keys", preventing them from being garbage collected @@ -34,8 +37,10 @@ type IdentityManager struct { type owner struct{} // UpdateIdentities is a callback when identities are updated -func (o *owner) UpdateIdentities(_, _ identity.IdentityMap) { - // no-op +func (o *owner) UpdateIdentities(_, _ identity.IdentityMap) <-chan struct{} { + ch := make(chan struct{}) + close(ch) + return ch } // GetNodeSuffix() is only used for KVStoreBackend (we use CRDBackend) @@ -43,15 +48,31 @@ func (o *owner) GetNodeSuffix() string { return "" } -func NewIdentityManager(l logrus.FieldLogger, client versioned.Interface) (*IdentityManager, error) { +func NewIdentityManager(ctx context.Context, l *slog.Logger, client versioned.Interface) (*IdentityManager, error) { + // Configure the allocator with a reasonable timeout for identity operations + allocConfig := cache.AllocatorConfig{ + Timeout: identityAllocatorTimeout, + SyncInterval: 1 * time.Hour, + } + im := &IdentityManager{ - l: l.WithField("component", "identitymanager"), - alloc: cache.NewCachingIdentityAllocator(&owner{}, cache.AllocatorConfig{}), + l: l.With("component", "identitymanager"), + alloc: cache.NewCachingIdentityAllocator(l, &owner{}, allocConfig), labelIdentities: make(map[string]identity.NumericIdentity), } im.l.Info("initializing identity allocator") - _ = im.alloc.InitIdentityAllocator(client) + initCh := im.alloc.InitIdentityAllocator(client, nil) + + // Wait for the identity allocator to be initialized (backend is created) + // Note: This doesn't wait for the full cache sync - that happens on first allocation + select { + case <-initCh: + im.l.Info("identity allocator initialized successfully") + case <-ctx.Done(): + return nil, errors.Wrap(ctx.Err(), "context cancelled while waiting for identity allocator initialization") + } + return im, nil } @@ -62,13 +83,13 @@ func (im *IdentityManager) DecrementReference(ctx context.Context, lbls labels.L sortedLabels := lbls.String() id, ok := im.labelIdentities[sortedLabels] if !ok { - im.l.WithField("labels", sortedLabels).Warn("expected identity for labels") + im.l.Warn("expected identity for labels", "labels", sortedLabels) return } idObj := im.alloc.LookupIdentityByID(ctx, id) if idObj == nil { - im.l.WithField("identity", id).Warn("expected identity for id") + im.l.Warn("expected identity for id", "identity", id) return } @@ -83,11 +104,10 @@ func (im *IdentityManager) DecrementReference(ctx context.Context, lbls labels.L // possible errors are // 1. ctx cancelled (in which case, hive is shutting down) // 2. identity not found in localKeys cache (nothing to worry about, and GC on CiliumIdentities will work as expected) - im.l.WithError(err).WithFields(logrus.Fields{ - "identity": idObj, - "identityLabels": idObj.Labels, - }).Warning( - "error while releasing previously allocated identity", + im.l.Warn("error while releasing previously allocated identity", + "error", err, + "identity", idObj, + "identityLabels", idObj.Labels, ) } @@ -95,11 +115,9 @@ func (im *IdentityManager) DecrementReference(ctx context.Context, lbls labels.L return } - im.l.WithFields(logrus.Fields{ - "identity": idObj, - "identityLabels": idObj.Labels, - }).Info( - "released identity due to no more references", + im.l.Info("released identity due to no more references", + "identity", idObj, + "identityLabels", idObj.Labels, ) delete(im.labelIdentities, sortedLabels) @@ -112,8 +130,8 @@ func (im *IdentityManager) GetIdentityAndIncrementReference(ctx context.Context, // notifyOwner=false because no need to notify owner (via UpdateIdentities callback). // oldNID=identity.InvalidIdentity would only be used for local identities (e.g. node-local CIDR identity), which we don't use. // Since this operation will create the CiliumIdentity if needed, - // pass in a context that completes either once ctx is done or kvstore timeout is reached. - allocateCtx, cancel := context.WithTimeout(ctx, option.Config.KVstoreConnectivityTimeout) + // pass in a context that completes either once ctx is done or identity allocator timeout is reached. + allocateCtx, cancel := context.WithTimeout(ctx, identityAllocatorTimeout) defer cancel() idObj, _, err := im.alloc.AllocateIdentity(allocateCtx, lbls, false, identity.InvalidIdentity) if err != nil { diff --git a/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux_test.go b/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux_test.go index 719f6a29c5..65e2d658b4 100644 --- a/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux_test.go +++ b/pkg/controllers/operator/cilium-crds/endpoint/identitymanager_linux_test.go @@ -2,12 +2,12 @@ package endpointcontroller import ( "context" + "log/slog" "strconv" "testing" - ciliumutil "github.com/microsoft/retina/pkg/utils/testutil/cilium" + ciliumclient "github.com/cilium/cilium/pkg/k8s/client/testutils" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,12 +17,14 @@ import ( ) func TestGetIdentities(t *testing.T) { - l := logrus.New() - m := ciliumutil.NewMockVersionedClient(l, nil) + ctx := context.Background() + l := slog.Default() + // Use Cilium's fake clientset which has proper watch support for the identity allocator + fakeClientSet, _ := ciliumclient.NewFakeClientset(l) // make sure to use CRD mode (this is referenced in InitIdentityAllocator) option.Config.IdentityAllocationMode = option.IdentityAllocationModeCRD - im, err := NewIdentityManager(l, m) + im, err := NewIdentityManager(ctx, l, fakeClientSet.CiliumFakeClientset) require.NoError(t, err) lbls := labels.Labels{ @@ -45,14 +47,16 @@ func TestGetIdentities(t *testing.T) { require.Greater(t, int(id), 0) // identity should be in API Server - idObj, err := m.CiliumV2().CiliumIdentities().Get(context.TODO(), strconv.FormatInt(id, 10), metav1.GetOptions{}) + idObj, err := fakeClientSet.CiliumFakeClientset.CiliumV2().CiliumIdentities().Get( + context.TODO(), strconv.FormatInt(id, 10), metav1.GetOptions{}) require.NoError(t, err) require.Equal(t, strconv.FormatInt(id, 10), idObj.Name) + // Cilium's CRD identity backend stores labels in SecurityLabels with source:key format idLabels := map[string]string{ - "k1": "v1", - "io.kubernetes.pod.namespace": "x", + "k8s:k1": "v1", + "k8s:io.kubernetes.pod.namespace": "x", } - require.Equal(t, idLabels, idObj.Labels) + require.Equal(t, idLabels, idObj.SecurityLabels) // same labels should return the same identity id2, err := im.GetIdentityAndIncrementReference(context.TODO(), lbls) @@ -88,23 +92,26 @@ func TestGetIdentities(t *testing.T) { require.Greater(t, int(id), 0) // identity should be in API Server - idObj, err = m.CiliumV2().CiliumIdentities().Get(context.TODO(), strconv.FormatInt(id3, 10), metav1.GetOptions{}) + idObj, err = fakeClientSet.CiliumFakeClientset.CiliumV2().CiliumIdentities().Get( + context.TODO(), strconv.FormatInt(id3, 10), metav1.GetOptions{}) require.NoError(t, err) require.Equal(t, strconv.FormatInt(id3, 10), idObj.Name) idLabels = map[string]string{ - "k1": "v1", - "k2": "v2", - "io.kubernetes.pod.namespace": "x", + "k8s:k1": "v1", + "k8s:k2": "v2", + "k8s:io.kubernetes.pod.namespace": "x", } - require.Equal(t, idLabels, idObj.Labels) + require.Equal(t, idLabels, idObj.SecurityLabels) } func TestDecrementReference(t *testing.T) { - l := logrus.New() - m := ciliumutil.NewMockVersionedClient(l, nil) + ctx := context.Background() + l := slog.Default() + // Use Cilium's fake clientset which has proper watch support for the identity allocator + fakeClientSet, _ := ciliumclient.NewFakeClientset(l) // make sure to use CRD mode (this is referenced in InitIdentityAllocator) option.Config.IdentityAllocationMode = option.IdentityAllocationModeCRD - im, err := NewIdentityManager(l, m) + im, err := NewIdentityManager(ctx, l, fakeClientSet.CiliumFakeClientset) require.NoError(t, err) lbls := labels.Labels{ @@ -134,12 +141,13 @@ func TestDecrementReference(t *testing.T) { require.Empty(t, im.labelIdentities) // IdentityManager's allocator should not delete the identity (identitygc cell does garbage collection) - idObj, err := m.CiliumV2().CiliumIdentities().Get(context.TODO(), strconv.FormatInt(id, 10), metav1.GetOptions{}) + idObj, err := fakeClientSet.CiliumFakeClientset.CiliumV2().CiliumIdentities().Get( + context.TODO(), strconv.FormatInt(id, 10), metav1.GetOptions{}) require.NoError(t, err) require.Equal(t, strconv.FormatInt(id, 10), idObj.Name) idLabels := map[string]string{ - "k1": "v1", - "io.kubernetes.pod.namespace": "x", + "k8s:k1": "v1", + "k8s:io.kubernetes.pod.namespace": "x", } - require.Equal(t, idLabels, idObj.Labels) + require.Equal(t, idLabels, idObj.SecurityLabels) } diff --git a/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go b/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go index 1f5a4444b5..4a654039a9 100644 --- a/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go +++ b/pkg/controllers/operator/retinaendpoint/retinaendpoint_controller_test.go @@ -224,15 +224,24 @@ func TestRetinaEndpointReconciler_ReconcilePod(t *testing.T) { return apierrors.IsNotFound(err) }, 5*time.Second, 1*time.Second, "RetinaEndpoint should not exist") } else { + // Wait for the RetinaEndpoint to be created/updated with the expected values require.Eventually(t, func() bool { err := client.Get(context.Background(), tt.fields.newlyCachedPod.Key, &got) - fmt.Println(err) if apierrors.IsNotFound(err) { return false } + // Check that the spec matches what we expect (indicating create/update completed) return got.Spec.PodIP == tt.wantedRetinaEndpoint.Spec.PodIP - }, 5*time.Second, 1*time.Second, "RetinaEndpoint should be created/updated") - require.Equal(t, *tt.wantedRetinaEndpoint, got) + }, 5*time.Second, 100*time.Millisecond, "RetinaEndpoint should be created/updated with expected PodIP") + + // Re-fetch to get the latest state + err := client.Get(context.Background(), tt.fields.newlyCachedPod.Key, &got) + require.NoError(t, err) + + // Compare the spec (ignore TypeMeta/ResourceVersion since fake client doesn't populate them) + require.Equal(t, tt.wantedRetinaEndpoint.Spec, got.Spec) + require.Equal(t, tt.wantedRetinaEndpoint.Name, got.Name) + require.Equal(t, tt.wantedRetinaEndpoint.Namespace, got.Namespace) } }) } diff --git a/pkg/hubble/parser/layer34/parser_linux.go b/pkg/hubble/parser/layer34/parser_linux.go index 74c1b4906a..9470c22650 100644 --- a/pkg/hubble/parser/layer34/parser_linux.go +++ b/pkg/hubble/parser/layer34/parser_linux.go @@ -2,6 +2,7 @@ package layer34 import ( "fmt" + "log/slog" "net/netip" "github.com/cilium/cilium/api/v1/flow" @@ -9,19 +10,17 @@ import ( "github.com/microsoft/retina/pkg/hubble/common" "github.com/microsoft/retina/pkg/utils" - "github.com/sirupsen/logrus" - "go.uber.org/zap" ) type Parser struct { - l *logrus.Entry + l *slog.Logger svd common.SvcDecoder epd common.EpDecoder } -func New(l *logrus.Entry, svc common.SvcDecoder, c *ipc.IPCache, labelCache common.LabelCache) *Parser { +func New(l *slog.Logger, svc common.SvcDecoder, c *ipc.IPCache, labelCache common.LabelCache) *Parser { p := &Parser{ - l: l.WithField("subsys", "layer34"), + l: l.With("subsys", "layer34"), svd: svc, epd: common.NewEpDecoder(c, labelCache), } @@ -35,17 +34,17 @@ func (p *Parser) Decode(f *flow.Flow) *flow.Flow { return nil } if f.GetIP() == nil { - p.l.Warn("Failed to get IP from flow", zap.Any("flow", f)) + p.l.Warn("Failed to get IP from flow", "flow", f) return f } sourceIP, err := netip.ParseAddr(f.GetIP().GetSource()) if err != nil { - p.l.Warn("Failed to parse source IP", zap.Error(err)) + p.l.Warn("Failed to parse source IP", "error", err) return f } destIP, err := netip.ParseAddr(f.GetIP().GetDestination()) if err != nil { - p.l.Warn("Failed to parse destination IP", zap.Error(err)) + p.l.Warn("Failed to parse destination IP", "error", err) return f } diff --git a/pkg/hubble/parser/parser_linux.go b/pkg/hubble/parser/parser_linux.go index 2aaa698ea3..6975a68b43 100644 --- a/pkg/hubble/parser/parser_linux.go +++ b/pkg/hubble/parser/parser_linux.go @@ -2,6 +2,7 @@ package parser import ( "errors" + "log/slog" "github.com/cilium/cilium/api/v1/flow" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" @@ -13,8 +14,6 @@ import ( "github.com/microsoft/retina/pkg/hubble/parser/layer34" "github.com/microsoft/retina/pkg/hubble/parser/seven" - "github.com/sirupsen/logrus" - "go.uber.org/zap" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -28,7 +27,7 @@ var ( type Params struct { cell.In - Logger logrus.FieldLogger + Logger *slog.Logger ServiceReconciler common.SvcDecoder LabelCache common.LabelCache @@ -36,14 +35,14 @@ type Params struct { } type Parser struct { - l *logrus.Entry + l *slog.Logger l34 *layer34.Parser l7 *seven.Parser } func New(params Params) parser.Decoder { - logger := params.Logger.WithField("subsys", "payloadparser") + logger := params.Logger.With("subsys", "payloadparser") return &Parser{ l: logger, @@ -84,11 +83,11 @@ func (p *Parser) _decode(event *v1.Event) *flow.Flow { // node names. f, ok := event.Event.(*flow.Flow) if !ok { - p.l.Warn("Failed to cast event to flow", zap.Any("event", event.Event)) + p.l.Warn("Failed to cast event to flow", "event", event.Event) return nil } if f == nil { - p.l.Warn("Failed to get flow from event", zap.Any("event", event)) + p.l.Warn("Failed to get flow from event", "event", event) return nil } @@ -99,9 +98,9 @@ func (p *Parser) _decode(event *v1.Event) *flow.Flow { case flow.FlowType_L7: f = p.l7.Decode(f) default: - p.l.Warn("Unknown flow type", zap.Any("flow", f)) + p.l.Warn("Unknown flow type", "flow", f) } - p.l.Debug("Enriched flow", zap.Any("flow", f)) + p.l.Debug("Enriched flow", "flow", f) return f } diff --git a/pkg/hubble/parser/seven/parser_linux.go b/pkg/hubble/parser/seven/parser_linux.go index 0fb7cb4e18..bd5d9d1ec0 100644 --- a/pkg/hubble/parser/seven/parser_linux.go +++ b/pkg/hubble/parser/seven/parser_linux.go @@ -2,6 +2,7 @@ package seven import ( "fmt" + "log/slog" "net/netip" "strings" @@ -9,19 +10,17 @@ import ( ipc "github.com/cilium/cilium/pkg/ipcache" "github.com/google/gopacket/layers" "github.com/microsoft/retina/pkg/hubble/common" - "github.com/sirupsen/logrus" - "go.uber.org/zap" ) type Parser struct { - l *logrus.Entry + l *slog.Logger svd common.SvcDecoder epd common.EpDecoder } -func New(l *logrus.Entry, svc common.SvcDecoder, c *ipc.IPCache, labelCache common.LabelCache) *Parser { +func New(l *slog.Logger, svc common.SvcDecoder, c *ipc.IPCache, labelCache common.LabelCache) *Parser { return &Parser{ - l: l.WithField("subsys", "seven"), + l: l.With("subsys", "seven"), svd: svc, epd: common.NewEpDecoder(c, labelCache), } @@ -62,17 +61,17 @@ func (p *Parser) decodeIP(f *flow.Flow) { // Decode the flow's source and destination IPs to their respective service. if f.GetIP() == nil { - p.l.Warn("Failed to get IP from flow", zap.Any("flow", f)) + p.l.Warn("Failed to get IP from flow", "flow", f) return } sourceIP, err := netip.ParseAddr(f.GetIP().GetSource()) if err != nil { - p.l.Warn("Failed to parse source IP", zap.Error(err)) + p.l.Warn("Failed to parse source IP", "error", err) return } destIP, err := netip.ParseAddr(f.GetIP().GetDestination()) if err != nil { - p.l.Warn("Failed to parse destination IP", zap.Error(err)) + p.l.Warn("Failed to parse destination IP", "error", err) return } diff --git a/pkg/k8s/apiserver_linux.go b/pkg/k8s/apiserver_linux.go index 22ae30c060..32fd2b8fae 100644 --- a/pkg/k8s/apiserver_linux.go +++ b/pkg/k8s/apiserver_linux.go @@ -1,19 +1,20 @@ package k8s import ( + "log/slog" + "github.com/cilium/cilium/pkg/identity" "github.com/cilium/cilium/pkg/ipcache" "github.com/cilium/cilium/pkg/source" "github.com/cilium/hive/cell" "github.com/microsoft/retina/pkg/common" cc "github.com/microsoft/retina/pkg/controllers/cache" - "github.com/sirupsen/logrus" ) type params struct { cell.In - Logger logrus.FieldLogger + Logger *slog.Logger IPCache *ipcache.IPCache Lifecycle cell.Lifecycle } @@ -28,58 +29,53 @@ func newAPIServerEventHandler(p params) *APIServerEventHandler { type APIServerEventHandler struct { c *ipcache.IPCache - l logrus.FieldLogger + l *slog.Logger } func (a *APIServerEventHandler) handleAPIServerEvent(event interface{}) { cacheEvent, ok := event.(*cc.CacheEvent) if !ok { - a.l.WithField("Event", event).Warn("Received unknown event type") + a.l.Warn("Received unknown event type", "event", event) return } switch cacheEvent.Type { //nolint:exhaustive // the default case adequately handles these case cc.EventTypeAddAPIServerIPs: apiserverObj, ok := cacheEvent.Obj.(*common.APIServerObject) if !ok { - a.l.WithField("Cache Event", cacheEvent).Warn("Received unknown event type") + a.l.Warn("Received unknown event type", "cacheEvent", cacheEvent) return } ips := apiserverObj.IPs() if len(ips) == 0 { - a.l.WithField("Cache Event", cacheEvent).Warn("Received empty API server IPs") + a.l.Warn("Received empty API server IPs", "cacheEvent", cacheEvent) return } for _, ip := range ips { //nolint:staticcheck // TODO(timraymond): unclear how to migrate this _, err := a.c.Upsert(ip.String(), nil, 0, nil, ipcache.Identity{ID: identity.ReservedIdentityKubeAPIServer, Source: source.Kubernetes}) if err != nil { - a.l.WithError(err).WithFields(logrus.Fields{ - "IP": ip.String(), - }).Error("Failed to add API server IPs to ipcache") + a.l.Error("Failed to add API server IPs to ipcache", "error", err, "ip", ip.String()) return } } - a.l.Infof("Added API server IPs %v to ipcache", ips) + a.l.Info("Added API server IPs to ipcache", "ips", ips) case cc.EventTypeDeleteAPIServerIPs: apiserverObj, ok := cacheEvent.Obj.(*common.APIServerObject) if !ok { - a.l.WithField("Cache Event", cacheEvent).Warn("Received unknown event type") + a.l.Warn("Received unknown event type", "cacheEvent", cacheEvent) return } ips := apiserverObj.IPs() if len(ips) == 0 { - a.l.WithField("Cache Event", cacheEvent).Warn("Received empty API server IPs") + a.l.Warn("Received empty API server IPs", "cacheEvent", cacheEvent) return } for _, ip := range ips { //nolint:staticcheck // TODO(timraymond): unclear how to migrate this a.c.Delete(ip.String(), source.Kubernetes) } - a.l.Infof("Deleted API server IPs %v from ipcache", ips) + a.l.Info("Deleted API server IPs from ipcache", "ips", ips) default: - a.l.WithFields(logrus.Fields{ - "Cache Event": cacheEvent, - "Type": cacheEvent.Type, - }).Warn("Received unknown cache event") + a.l.Warn("Received unknown cache event", "cacheEvent", cacheEvent, "type", cacheEvent.Type) } } diff --git a/pkg/k8s/cell_linux.go b/pkg/k8s/cell_linux.go index 72fda13ae8..93e6a29c4f 100644 --- a/pkg/k8s/cell_linux.go +++ b/pkg/k8s/cell_linux.go @@ -2,14 +2,19 @@ package k8s import ( "context" + "fmt" "log/slog" daemonk8s "github.com/cilium/cilium/daemon/k8s" cgmngr "github.com/cilium/cilium/pkg/cgroups/manager" + cmtypes "github.com/cilium/cilium/pkg/clustermesh/types" + fakedp "github.com/cilium/cilium/pkg/datapath/fake/types" "github.com/cilium/cilium/pkg/datapath/iptables/ipset" "github.com/cilium/cilium/pkg/datapath/tables" datapath "github.com/cilium/cilium/pkg/datapath/types" "github.com/cilium/cilium/pkg/endpointmanager" + "github.com/cilium/cilium/pkg/endpointstate" + "github.com/cilium/cilium/pkg/identity" "github.com/cilium/cilium/pkg/identity/cache" identitycachecell "github.com/cilium/cilium/pkg/identity/cache/cell" "github.com/cilium/cilium/pkg/ipcache" @@ -23,47 +28,109 @@ import ( "github.com/cilium/cilium/pkg/k8s/synced" k8sTypes "github.com/cilium/cilium/pkg/k8s/types" "github.com/cilium/cilium/pkg/k8s/watchers" + "github.com/cilium/cilium/pkg/labelsfilter" + "github.com/cilium/cilium/pkg/loadbalancer" "github.com/cilium/cilium/pkg/metrics" "github.com/cilium/cilium/pkg/node" "github.com/cilium/cilium/pkg/policy" - "github.com/cilium/cilium/pkg/redirectpolicy" - "github.com/cilium/cilium/pkg/service" + policycell "github.com/cilium/cilium/pkg/policy/cell" + "github.com/cilium/cilium/pkg/promise" + testidentity "github.com/cilium/cilium/pkg/testutils/identity" + wgtypes "github.com/cilium/cilium/pkg/wireguard/types" "github.com/cilium/hive/cell" "github.com/cilium/statedb" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/workqueue" + "github.com/microsoft/retina/pkg/common" "github.com/microsoft/retina/pkg/pubsub" - "github.com/sirupsen/logrus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// Cell provides the Kubernetes watchers needed by Hubble flow enrichment. +// It is broken into sub-cells so that when Cilium changes its DI graph +// upstream, the failing sub-cell immediately identifies which dependency +// boundary broke. var Cell = cell.Module( "k8s-watcher", - "Kubernetes watchers needed by the agent", + "Kubernetes watchers needed by Hubble flow enrichment", + infrastructureCell, + ipcacheCell, + watcherCell, + stubsCell, +) + +// infrastructureCell provides StateDB tables, metrics, cgroups, and other +// foundational components that Cilium's internals depend on. +// Breaks when: Cilium adds new table types or changes table registration APIs. +var infrastructureCell = cell.Group( daemonk8s.PodTableCell, + daemonk8s.NamespaceTableCell, cell.Provide( tables.NewDeviceTable, statedb.RWTable[*tables.Device].ToTable, ), - cell.Invoke(func(db *statedb.DB, t statedb.Table[*tables.Device]) { - err := db.RegisterTable(t) - if err != nil { - logrus.WithError(err).Fatal("Failed to register table") - } + // Service cache tables + cell.Provide(func(db *statedb.DB) (statedb.RWTable[tables.NodeAddress], error) { + return statedb.NewTable(db, tables.NodeAddressTableName, tables.NodeAddressIndex) }), + cell.Provide(statedb.RWTable[tables.NodeAddress].ToTable), + + // Loadbalancer config (required by some Cilium cells) + loadbalancer.ConfigCell, + cell.Provide(newFrontendsTable), + + // Cluster info + cell.Provide(func() cmtypes.ClusterInfo { return cmtypes.DefaultClusterInfo }), + + metrics.Cell, + cgmngr.Cell, +) + +// ipcacheCell provides identity allocation and IPCache — the core +// components Hubble uses to enrich flows with pod/namespace metadata. +// Breaks when: Cilium changes identity allocator APIs or IPCache config. +var ipcacheCell = cell.Group( + identitycachecell.Cell, + endpointmanager.Cell, + + cell.Invoke(initLabelFilter), + cell.Provide(newIPCache), + + node.LocalNodeStoreCell, + cell.Provide(newNodeSynchronizer), +) + +// watcherCell sets up K8s resource watches for CiliumEndpoint, Services, +// and Endpoints. These feed data into IPCache for flow enrichment. +// Breaks when: Cilium changes resource constructor signatures or watcher config. +var watcherCell = cell.Group( + cell.Provide(newCiliumEndpointResource), + cell.Provide(newEndpointsResource), + cell.Provide(newServiceResource), + + cell.Provide(func() watchers.WatcherConfiguration { return &watcherconfig{} }), + cell.Provide(func() watchers.ResourceGroupFunc { return watcherResourceGroups }), + + synced.Cell, + watchers.Cell, + + cell.Provide(newAPIServerEventHandler), + cell.Invoke(subscribeAPIServerEvents), +) +// stubsCell provides no-op implementations for Cilium features that Retina +// doesn't use (policy engine, datapath, wireguard, ipsec, etc.). These +// satisfy DI requirements without any real functionality. +// Breaks when: Cilium adds new required providers or changes interfaces. +var stubsCell = cell.Group( + // Fake K8s resources for features Retina doesn't watch cell.Provide( - func() resource.Resource[*slim_corev1.Namespace] { - return &fakeresource[*slim_corev1.Namespace]{} - }, - func() daemonk8s.LocalNodeResource { - return &fakeresource[*slim_corev1.Node]{} - }, - func() daemonk8s.LocalCiliumNodeResource { - return &fakeresource[*cilium_api_v2.CiliumNode]{} - }, + func() resource.Resource[*slim_corev1.Namespace] { return &fakeresource[*slim_corev1.Namespace]{} }, + func() daemonk8s.LocalNodeResource { return &fakeresource[*slim_corev1.Node]{} }, + func() daemonk8s.LocalCiliumNodeResource { return &fakeresource[*cilium_api_v2.CiliumNode]{} }, func() resource.Resource[*slim_networkingv1.NetworkPolicy] { return &fakeresource[*slim_networkingv1.NetworkPolicy]{} }, @@ -76,156 +143,136 @@ var Cell = cell.Module( func() resource.Resource[*cilium_api_v2alpha1.CiliumCIDRGroup] { return &fakeresource[*cilium_api_v2alpha1.CiliumCIDRGroup]{} }, + func() resource.Resource[*cilium_api_v2.CiliumCIDRGroup] { + return &fakeresource[*cilium_api_v2.CiliumCIDRGroup]{} + }, func() resource.Resource[*cilium_api_v2alpha1.CiliumEndpointSlice] { return &fakeresource[*cilium_api_v2alpha1.CiliumEndpointSlice]{} }, func() resource.Resource[*cilium_api_v2.CiliumNode] { return &fakeresource[*cilium_api_v2.CiliumNode]{} }, - func() watchers.WatcherConfiguration { - return &watcherconfig{} - }, ), - svcCacheCell, - - metrics.Cell, - - endpointmanager.Cell, - - cell.Provide(func() *policy.Updater { - return &policy.Updater{} - }), - - cell.Provide(func() *redirectpolicy.Manager { - return &redirectpolicy.Manager{} - }), - - cell.Provide(func() datapath.BandwidthManager { - return &fakeBandwidthManager{} - }), - - cell.Provide(func() service.ServiceManager { - return &service.Service{} - }), - - cgmngr.Cell, - - // Provide the resources needed by the watchers. - - cell.Provide(func(lc cell.Lifecycle, cs client.Clientset) (resource.Resource[*k8sTypes.CiliumEndpoint], error) { - return ciliumk8s.CiliumSlimEndpointResource(ciliumk8s.CiliumResourceParams{ - Lifecycle: lc, - ClientSet: cs, - }, nil, func(*metav1.ListOptions) {}) - }), - - cell.Provide(func(l *slog.Logger, lc cell.Lifecycle, cs client.Clientset) (resource.Resource[*ciliumk8s.Endpoints], error) { - //nolint:wrapcheck // a wrapped error here is of dubious value - return ciliumk8s.EndpointsResource(l, lc, ciliumk8s.Config{ - EnableK8sEndpointSlice: true, - K8sServiceProxyName: "", - }, cs) - }), - - cell.Provide(func(lc cell.Lifecycle, cs client.Clientset) (resource.Resource[*slim_corev1.Service], error) { - //nolint:wrapcheck // a wrapped error here is of dubious value - return ciliumk8s.ServiceResource( - lc, - ciliumk8s.Config{ - EnableK8sEndpointSlice: false, - }, - cs, - func(*metav1.ListOptions) {}, - ) - }), - + // No-op policy/datapath (Retina doesn't use Cilium's policy engine). + // Uses Cilium's own fake types from pkg/datapath/fake/types where available. cell.Provide( - func() policy.PolicyRepository { - return &NoOpPolicyRepository{} - }, - func() datapath.Orchestrator { - return &NoOpOrchestrator{} + func() policy.PolicyRepository { return &NoOpPolicyRepository{} }, + func() datapath.Orchestrator { return &fakedp.FakeOrchestrator{} }, + func() policycell.IdentityUpdater { return &noOpIdentityUpdater{} }, + func() *policy.Updater { return &policy.Updater{} }, + func() datapath.BandwidthManager { return &fakedp.BandwidthManager{} }, + func() ipset.Manager { return &fakedp.IPSet{} }, + func() wgtypes.WireguardConfig { return fakedp.WireguardConfig{} }, + func() datapath.IPsecConfig { return fakedp.IPsecConfig{} }, + func() datapath.IptablesManager { return fakedp.NewIptablesManager() }, + func() promise.Promise[endpointstate.Restorer] { + r, p := promise.New[endpointstate.Restorer]() + r.Resolve(&fakeRestorer{}) + return p }, ), +) - identitycachecell.Cell, +// ============================================================ +// Helper functions +// ============================================================ - // Provide everything needed for the watchers. - cell.Provide( - func() *ipcache.IPCache { - alloc := cache.NewCachingIdentityAllocator( - &identityAllocatorOwner{}, - cache.AllocatorConfig{}, - ) - idAlloc := &cachingIdentityAllocator{ - alloc, - nil, - } - return ipcache.NewIPCache(&ipcache.Configuration{ - Context: context.Background(), - IdentityAllocator: idAlloc, - PolicyHandler: &policyhandler{}, - DatapathHandler: &datapathhandler{}, - }) - }, - ), +func initLabelFilter(l *slog.Logger) { + if err := labelsfilter.ParseLabelPrefixCfg(l, nil, nil, ""); err != nil { + l.Error("Failed to parse label prefix config", "error", err) + } +} - cell.Provide(func() node.LocalNodeSynchronizer { - return &nodeSynchronizer{ - l: logrus.WithField("module", "node-synchronizer"), - } - }), +func newIPCache(l *slog.Logger) *ipcache.IPCache { + alloc := cache.NewCachingIdentityAllocator( + l, + &testidentity.IdentityAllocatorOwnerMock{}, + cache.AllocatorConfig{}, + ) + return ipcache.NewIPCache(&ipcache.Configuration{ + Context: context.Background(), + Logger: l.With("module", "ipcache"), + IdentityAllocator: alloc, + IdentityUpdater: &noOpIdentityUpdater{}, + }) +} - cell.Provide(func() ipset.Manager { - return &fakeIpsetMgr{} - }), +func newNodeSynchronizer(l *slog.Logger) node.LocalNodeSynchronizer { + return &nodeSynchronizer{l: l.With("module", "node-synchronizer")} +} - node.LocalNodeStoreCell, +func newCiliumEndpointResource( + lc cell.Lifecycle, cs client.Clientset, mp workqueue.MetricsProvider, +) (resource.Resource[*k8sTypes.CiliumEndpoint], error) { + //nolint:wrapcheck // wrapped error here is of dubious value + return ciliumk8s.CiliumSlimEndpointResource(ciliumk8s.CiliumResourceParams{ + Lifecycle: lc, + ClientSet: cs, + }, nil, mp, func(*metav1.ListOptions) {}) +} - synced.Cell, - cell.Provide(newAPIServerEventHandler), +func newEndpointsResource( + l *slog.Logger, lc cell.Lifecycle, cs client.Clientset, mp workqueue.MetricsProvider, +) (resource.Resource[*ciliumk8s.Endpoints], error) { + //nolint:wrapcheck // wrapped error here is of dubious value + return ciliumk8s.EndpointsResource(l, lc, ciliumk8s.ConfigParams{ + Config: ciliumk8s.Config{K8sServiceProxyName: ""}, + WatchConfig: ciliumk8s.ServiceWatchConfig{EnableHeadlessServiceWatch: true}, + }, cs, mp) +} - cell.Provide(func() watchers.ResourceGroupFunc { return watcherResourceGroups }), +func newServiceResource( + lc cell.Lifecycle, cs client.Clientset, mp workqueue.MetricsProvider, +) (resource.Resource[*slim_corev1.Service], error) { + //nolint:wrapcheck // wrapped error here is of dubious value + return ciliumk8s.ServiceResource( + lc, + ciliumk8s.ConfigParams{ + Config: ciliumk8s.Config{K8sServiceProxyName: ""}, + WatchConfig: ciliumk8s.ServiceWatchConfig{EnableHeadlessServiceWatch: false}, + }, + cs, + mp, + func(*metav1.ListOptions) {}, + ) +} - watchers.Cell, +func newFrontendsTable(cfg loadbalancer.Config, db *statedb.DB) (statedb.Table[*loadbalancer.Frontend], error) { + tbl, err := loadbalancer.NewFrontendsTable(cfg, db) + if err != nil { + return nil, fmt.Errorf("failed to create frontends table: %w", err) + } + return tbl, nil +} - cell.Invoke(func(a *APIServerEventHandler) { - ps := pubsub.New() - fn := pubsub.CallBackFunc(a.handleAPIServerEvent) - uuid := ps.Subscribe(common.PubSubAPIServer, &fn) - a.l.WithFields(logrus.Fields{ - "uuid": uuid, - }).Info("Subscribed to PubSub APIServer") - }), -) +func subscribeAPIServerEvents(a *APIServerEventHandler) { + ps := pubsub.New() + fn := pubsub.CallBackFunc(a.handleAPIServerEvent) + uuid := ps.Subscribe(common.PubSubAPIServer, &fn) + a.l.Info("Subscribed to PubSub APIServer", "uuid", uuid) +} -var svcCacheCell = cell.Group( - cell.Provide(func() (statedb.Table[tables.NodeAddress], error) { - return statedb.NewTable(tables.NodeAddressTableName, tables.NodeAddressIndex) - }), - cell.Invoke(func(db *statedb.DB, t statedb.Table[tables.NodeAddress]) { - err := db.RegisterTable(t) - if err != nil { - logrus.WithError(err).Fatal("Failed to register table") - } - }), - cell.Provide(ciliumk8s.NewSVCMetricsNoop), - cell.Provide(ciliumk8s.NewServiceCache), - cell.Provide(func(svcCache *ciliumk8s.ServiceCacheImpl) ciliumk8s.ServiceCache { - return svcCache - }), -) +// ============================================================ +// Watcher configuration +// ============================================================ -const ( - K8sAPIGroupCiliumEndpointV2 = "cilium/v2::CiliumEndpoint" - K8sAPIGroupServiceV1Core = "core/v1::Service" -) +const K8sAPIGroupCiliumEndpointV2 = "cilium/v2::CiliumEndpoint" -var k8sResources = []string{K8sAPIGroupCiliumEndpointV2, K8sAPIGroupServiceV1Core} +var k8sResources = []string{K8sAPIGroupCiliumEndpointV2} -// resourceGroups are all of the core Kubernetes and Cilium resource groups -// which the Cilium agent watches to implement CNI functionality. func watcherResourceGroups(*slog.Logger, watchers.WatcherConfiguration) (r, w []string) { return k8sResources, w } + +// ============================================================ +// No-op identity updater +// ============================================================ + +type noOpIdentityUpdater struct{} + +func (n *noOpIdentityUpdater) UpdateIdentities(_, _ identity.IdentityMap) <-chan struct{} { + ch := make(chan struct{}) + close(ch) + return ch +} diff --git a/pkg/k8s/local_node_synchronizer_linux.go b/pkg/k8s/local_node_synchronizer_linux.go index 4ce5402d96..399bd2b4f4 100644 --- a/pkg/k8s/local_node_synchronizer_linux.go +++ b/pkg/k8s/local_node_synchronizer_linux.go @@ -2,17 +2,17 @@ package k8s import ( "context" + "log/slog" "net" "os" "github.com/cilium/cilium/pkg/node" "github.com/cilium/cilium/pkg/node/addressing" nodetypes "github.com/cilium/cilium/pkg/node/types" - "github.com/sirupsen/logrus" ) type nodeSynchronizer struct { - l *logrus.Entry + l *slog.Logger } func (n *nodeSynchronizer) InitLocalNode(_ context.Context, ln *node.LocalNode) error { diff --git a/pkg/k8s/placeholders_linux.go b/pkg/k8s/placeholders_linux.go index af145d03b0..8d97b8ceea 100644 --- a/pkg/k8s/placeholders_linux.go +++ b/pkg/k8s/placeholders_linux.go @@ -2,25 +2,14 @@ package k8s import ( "context" - "io" - "net" - "net/netip" - "sync" - "github.com/cilium/cilium/api/v1/models" "github.com/cilium/cilium/pkg/container/set" - "github.com/cilium/cilium/pkg/crypto/certificatemanager" - "github.com/cilium/cilium/pkg/datapath/iptables/ipset" - "github.com/cilium/cilium/pkg/datapath/loader/metrics" - datapathtypes "github.com/cilium/cilium/pkg/datapath/types" "github.com/cilium/cilium/pkg/identity" - "github.com/cilium/cilium/pkg/identity/cache" - "github.com/cilium/cilium/pkg/ipcache" ipcachetypes "github.com/cilium/cilium/pkg/ipcache/types" "github.com/cilium/cilium/pkg/k8s/resource" - "github.com/cilium/cilium/pkg/labels" "github.com/cilium/cilium/pkg/policy" "github.com/cilium/cilium/pkg/policy/api" + policytypes "github.com/cilium/cilium/pkg/policy/types" cilium "github.com/cilium/proxy/go/cilium/api" k8sRuntime "k8s.io/apimachinery/pkg/runtime" ) @@ -38,92 +27,10 @@ func (f *fakeresource[T]) Store(_ context.Context) (resource.Store[T], error) { func (f *fakeresource[T]) Observe(context.Context, func(resource.Event[T]), func(error)) { } -type watcherconfig struct { - internalconfigs -} - -func (w *watcherconfig) KVstoreEnabled() bool { - return false -} - -type internalconfigs struct{} - -func (w *internalconfigs) K8sNetworkPolicyEnabled() bool { - return false -} - -func (w *internalconfigs) K8sIngressControllerEnabled() bool { - return false -} - -func (w *internalconfigs) K8sGatewayAPIEnabled() bool { - return false -} - -func (w *internalconfigs) KVstoreEnabledWithoutPodNetworkSupport() bool { - return false -} - -type identityAllocatorOwner struct{} - -func (i *identityAllocatorOwner) UpdateIdentities(identity.IdentityMap, identity.IdentityMap) {} - -func (i *identityAllocatorOwner) GetNodeSuffix() string { - return "" -} - -type cachingIdentityAllocator struct { - *cache.CachingIdentityAllocator - ipcache *ipcache.IPCache -} - -func (c cachingIdentityAllocator) AllocateCIDRsForIPs([]net.IP, map[netip.Prefix]*identity.Identity) ([]*identity.Identity, error) { - return nil, nil -} - -func (c cachingIdentityAllocator) ReleaseCIDRIdentitiesByID(context.Context, []identity.NumericIdentity) { -} - -type policyhandler struct{} - -func (p *policyhandler) UpdateIdentities(identity.IdentityMap, identity.IdentityMap, *sync.WaitGroup) bool { - return false -} - -type datapathhandler struct{} - -func (d *datapathhandler) UpdatePolicyMaps(context.Context, *sync.WaitGroup) *sync.WaitGroup { - return &sync.WaitGroup{} -} - -type fakeBandwidthManager struct{} - -func (f *fakeBandwidthManager) BBREnabled() bool { - return false -} - -func (f *fakeBandwidthManager) Enabled() bool { - return false -} - -func (f *fakeBandwidthManager) UpdateBandwidthLimit(uint16, uint64, uint32) {} - -func (f *fakeBandwidthManager) DeleteBandwidthLimit(uint16) {} - -func (f *fakeBandwidthManager) UpdateIngressBandwidthLimit(uint16, uint64) { -} - -func (f *fakeBandwidthManager) DeleteIngressBandwidthLimit(uint16) {} - -type fakeIpsetMgr struct{} - -func (f *fakeIpsetMgr) NewInitializer() ipset.Initializer { - return nil -} - -func (f *fakeIpsetMgr) AddToIPSet(string, ipset.Family, ...netip.Addr) {} +type watcherconfig struct{} -func (f *fakeIpsetMgr) RemoveFromIPSet(string, ...netip.Addr) {} +func (w *watcherconfig) K8sNetworkPolicyEnabled() bool { return false } +func (w *watcherconfig) K8sClusterNetworkPolicyEnabled() bool { return false } // NoOpPolicyRepository is a no-op implementation of the PolicyRepository interface. type NoOpPolicyRepository struct{} @@ -156,43 +63,30 @@ func (n *NoOpPolicyRepository) GetSelectorCache() *policy.SelectorCache { return nil } -func (n *NoOpPolicyRepository) Iterate(func(*api.Rule)) {} - -func (n *NoOpPolicyRepository) ReplaceByResource(api.Rules, ipcachetypes.ResourceID) (affectedIDs *set.Set[identity.NumericIdentity], rev uint64, oldRevCnt int) { - return nil, 0, 0 +func (n *NoOpPolicyRepository) GetSubjectSelectorCache() *policy.SelectorCache { + return nil } -func (n *NoOpPolicyRepository) ReplaceByLabels(api.Rules, []labels.LabelArray) (affectedIDs *set.Set[identity.NumericIdentity], rev uint64, oldRevCnt int) { +func (n *NoOpPolicyRepository) Iterate(func(*policytypes.PolicyEntry)) {} + +func (n *NoOpPolicyRepository) ReplaceByResource( + _ policytypes.PolicyEntries, _ ipcachetypes.ResourceID, +) (affectedIDs *set.Set[identity.NumericIdentity], rev uint64, oldRevCnt int) { return nil, 0, 0 } -func (n *NoOpPolicyRepository) Search(labels.LabelArray) (r api.Rules, i uint64) { +func (n *NoOpPolicyRepository) Search() (entries policytypes.PolicyEntries, rev uint64) { return nil, 0 } -func (n *NoOpPolicyRepository) SetEnvoyRulesFunc(func(certificatemanager.SecretManager, *api.L7Rules, string, string) (*cilium.HttpNetworkPolicyRules, bool)) { -} - -type NoOpOrchestrator struct{} - -func (n *NoOpOrchestrator) Reinitialize(context.Context) error { +func (n *NoOpPolicyRepository) GetPolicySnapshot() map[identity.NumericIdentity]policy.SelectorPolicy { return nil } -func (n *NoOpOrchestrator) ReloadDatapath(context.Context, datapathtypes.Endpoint, *metrics.SpanStat) (string, error) { - return "", nil -} +// fakeRestorer is a no-op endpointstate.Restorer (Retina doesn't restore endpoints). +type fakeRestorer struct{} -func (n *NoOpOrchestrator) ReinitializeXDP(context.Context, []string) error { - return nil -} - -func (n *NoOpOrchestrator) EndpointHash(datapathtypes.EndpointConfiguration) (string, error) { - return "", nil -} - -func (n *NoOpOrchestrator) WriteEndpointConfig(io.Writer, datapathtypes.EndpointConfiguration) error { - return nil -} +func (fakeRestorer) WaitForEndpointRestoreWithoutRegeneration(context.Context) error { return nil } +func (fakeRestorer) WaitForEndpointRestore(context.Context) error { return nil } +func (fakeRestorer) WaitForInitialPolicy(context.Context) error { return nil } -func (n *NoOpOrchestrator) Unload(datapathtypes.Endpoint) {} diff --git a/pkg/k8s/watcher_linux.go b/pkg/k8s/watcher_linux.go index 14df5a0982..883d59f510 100644 --- a/pkg/k8s/watcher_linux.go +++ b/pkg/k8s/watcher_linux.go @@ -2,17 +2,18 @@ package k8s import ( "context" + "log/slog" "strings" + "sync" "time" "k8s.io/apimachinery/pkg/util/runtime" "github.com/cilium/cilium/pkg/k8s" "github.com/cilium/cilium/pkg/k8s/watchers" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/option" - "github.com/sirupsen/logrus" + retinalog "github.com/microsoft/retina/pkg/log" ) func init() { @@ -24,20 +25,25 @@ func init() { } var ( - logger = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s-watcher") + loggerOnce sync.Once + cachedLog *slog.Logger ) +// logger returns a zap-backed slog logger. Resolved lazily because +// SetupZapLogger runs later in program startup than this package's init(). +func logger() *slog.Logger { + loggerOnce.Do(func() { + cachedLog = retinalog.SlogLogger().With(logfields.LogSubsys, "k8s-watcher") + }) + return cachedLog +} + func Start(ctx context.Context, k *watchers.K8sWatcher) { - logger.Info("Starting Kubernetes watcher") + logger().Info("Starting Kubernetes watcher") option.Config.K8sSyncTimeout = 3 * time.Minute //nolint:gomnd // this duration is self-explanatory - syncdCache := make(chan struct{}) - go k.InitK8sSubsystem(ctx, syncdCache) - logger.WithField("k8s resources", k8sResources).Info("Kubernetes watcher started, will wait for cache sync") - - // Wait for K8s watcher to sync. If doesn't complete in 3 minutes, causes fatal error. - <-syncdCache - logger.Info("Kubernetes watcher synced") + k.InitK8sSubsystem(ctx) + logger().Info("Kubernetes watcher synced") } // retinaK8sErrorHandler is a custom error handler for the watcher @@ -46,17 +52,17 @@ func k8sWatcherErrorHandler(c context.Context, e error, s string, i ...interface if e == nil { // TODO: handle key/values pairs in a better way // current example output: time="2009-11-10T23:00:00Z" level=error msg="msg: Some error message -- key/values: [int 1 str world]" - logger.WithContext(c).Errorf("msg: %s -- key/values: %+v", s, i) + logger().ErrorContext(c, "msg: "+s, "key_values", i) return } errStr := e.Error() logError := func(er, r string) { - logger.WithFields(logrus.Fields{ - "underlyingError": er, - "resource": r, - }).Error("Error watching k8s resource") + logger().Error("Error watching k8s resource", + "underlyingError", er, + "resource", r, + ) } switch { diff --git a/pkg/log/export_test.go b/pkg/log/export_test.go new file mode 100644 index 0000000000..2fa5f380be --- /dev/null +++ b/pkg/log/export_test.go @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +package log + +import "sync" + +// resetGlobalForTest clears the zap global and the self-init once so each test +// can call SetupZapLogger with its own options. Tests in this package do not +// run in parallel, so no locking is required beyond the atomic store. +func resetGlobalForTest() { + global.Store(nil) + initOnce = sync.Once{} +} diff --git a/pkg/log/zap.go b/pkg/log/zap.go index 9d3e218d3b..dda5ebd461 100644 --- a/pkg/log/zap.go +++ b/pkg/log/zap.go @@ -3,22 +3,37 @@ package log import ( + "context" + "log/slog" "net/http" "os" "runtime" + "sync" + "sync/atomic" "time" "github.com/Azure/azure-container-networking/zapai" "github.com/go-chi/chi/middleware" + "github.com/go-logr/logr" + "github.com/go-logr/zapr" logfmt "github.com/jsternberg/zap-logfmt" "github.com/microsoft/ApplicationInsights-Go/appinsights" "github.com/pkg/errors" "go.uber.org/zap" + "go.uber.org/zap/exp/zapslog" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) -var global *ZapLogger +// global holds the configured ZapLogger. Written once by SetupZapLogger and +// read by every helper in this package; atomic for race-free access from +// goroutines started after (or concurrently with) SetupZapLogger. +var ( + global atomic.Pointer[ZapLogger] + initOnce sync.Once +) + +func loadGlobal() *ZapLogger { return global.Load() } const ( defaultFileName = "retina.log" @@ -46,7 +61,12 @@ func GetDefaultLogOpts() *LogOpts { } func Logger() *ZapLogger { - return global + initOnce.Do(func() { + if loadGlobal() == nil { + _, _ = SetupZapLogger(GetDefaultLogOpts()) + } + }) + return loadGlobal() } type ZapLogger struct { @@ -62,8 +82,8 @@ func EncoderConfig() zapcore.EncoderConfig { } func SetupZapLogger(lOpts *LogOpts, persistentFields ...zap.Field) (*ZapLogger, error) { - if global != nil { - return global, nil + if g := loadGlobal(); g != nil { + return g, nil } logger := &ZapLogger{} @@ -130,8 +150,8 @@ func SetupZapLogger(lOpts *LogOpts, persistentFields ...zap.Field) (*ZapLogger, core = zapcore.NewTee(core, filecore) } logger.Logger = zap.New(core, zap.AddCaller()) - global = logger - return global, nil + global.Store(logger) + return logger, nil } func (l *ZapLogger) Close() { @@ -202,3 +222,158 @@ func (lOpts *LogOpts) validate() { } } } + +// SlogHandler returns an slog.Handler backed by the global zap core. +// All slog messages will flow through zap's pipeline (stdout + Application Insights). +// The returned handler resolves the global zap core on every call, so it keeps +// working even if registered (e.g. via logging.AddHandlers) before SetupZapLogger +// runs — once the global is initialized, records start flowing to AI. +func SlogHandler() slog.Handler { + return &lazyZapHandler{} +} + +// lazyZapHandler resolves the Retina zap core at call time. This lets callers +// register a single slog.Handler into Cilium's MultiSlogHandler (or capture +// it via slog.Default/.With) before SetupZapLogger runs — once `global` is +// set, records flow through zap → stdout + Application Insights. +// +// `ops` records WithAttrs / WithGroup calls in their original order so the +// inner zap-backed handler is built with attribute-group nesting identical to +// what the caller requested (per the slog.Handler contract). +type lazyZapHandler struct { + ops []lazyOp +} + +type lazyOp struct { + attrs []slog.Attr // when non-nil, a WithAttrs op + group string // when attrs is nil and group != "", a WithGroup op +} + +func (h *lazyZapHandler) inner() slog.Handler { + g := loadGlobal() + if g == nil { + return nil + } + var sh slog.Handler = zapslog.NewHandler(g.Core(), zapslog.WithCaller(true)) + for _, op := range h.ops { + if op.attrs != nil { + sh = sh.WithAttrs(op.attrs) + } else { + sh = sh.WithGroup(op.group) + } + } + return sh +} + +func (h *lazyZapHandler) Enabled(ctx context.Context, lvl slog.Level) bool { + sh := h.inner() + if sh == nil { + return true // accept records; they'll be dropped below if still uninitialized + } + return sh.Enabled(ctx, lvl) +} + +func (h *lazyZapHandler) Handle(ctx context.Context, r slog.Record) error { + sh := h.inner() + if sh == nil { + return nil // zap not ready yet; Cilium's own text handler still logs to stderr + } + //nolint:wrapcheck // passthrough to the inner slog.Handler; wrapping would mangle zap diagnostics + return sh.Handle(ctx, r) +} + +func (h *lazyZapHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + if len(attrs) == 0 { + return h + } + ops := make([]lazyOp, len(h.ops), len(h.ops)+1) + copy(ops, h.ops) + ops = append(ops, lazyOp{attrs: attrs}) + return &lazyZapHandler{ops: ops} +} + +func (h *lazyZapHandler) WithGroup(name string) slog.Handler { + if name == "" { + return h // per slog.Handler contract + } + ops := make([]lazyOp, len(h.ops), len(h.ops)+1) + copy(ops, h.ops) + ops = append(ops, lazyOp{group: name}) + return &lazyZapHandler{ops: ops} +} + +// SetDefaultSlog sets Go's global slog default to use the zap-backed handler. +// After calling this, slog.Default() returns a logger that routes through zap. +func SetDefaultSlog() { + slog.SetDefault(slog.New(SlogHandler())) +} + +// SlogLogger returns a new *slog.Logger backed by the global zap core. +func SlogLogger() *slog.Logger { + return slog.New(SlogHandler()) +} + +// LogrLogger returns a logr.Logger backed by the global zap logger. +// This is useful for integrating with controller-runtime and other libraries +// that use logr.Logger, ensuring consistent log format across the application. +// +// The returned logr.Logger is backed by a logr.LogSink that resolves the zap +// core on every call, so controller-runtime loggers set up before +// SetupZapLogger runs automatically start flowing to Application Insights +// once the zap global is initialized. +func LogrLogger() logr.Logger { + return logr.New(&lazyLogrSink{}) +} + +// lazyLogrSink resolves the Retina zap.Logger on every call and delegates to +// a fresh zapr sink. A production-zap fallback keeps the sink safe to use +// before SetupZapLogger runs. +type lazyLogrSink struct { + name string + values []any +} + +func (s *lazyLogrSink) delegate() logr.LogSink { + g := loadGlobal() + var zl *zap.Logger + if g != nil { + zl = g.Logger + } else { + zl = zap.Must(zap.NewProduction()) + } + lr := zapr.NewLogger(zl) + if s.name != "" { + lr = lr.WithName(s.name) + } + if len(s.values) > 0 { + lr = lr.WithValues(s.values...) + } + return lr.GetSink() +} + +func (s *lazyLogrSink) Init(ri logr.RuntimeInfo) { s.delegate().Init(ri) } +func (s *lazyLogrSink) Enabled(level int) bool { return s.delegate().Enabled(level) } +func (s *lazyLogrSink) Info(level int, msg string, kv ...any) { + s.delegate().Info(level, msg, kv...) +} + +func (s *lazyLogrSink) Error(err error, msg string, kv ...any) { + s.delegate().Error(err, msg, kv...) +} + +func (s *lazyLogrSink) WithValues(kv ...any) logr.LogSink { + nv := make([]any, 0, len(s.values)+len(kv)) + nv = append(nv, s.values...) + nv = append(nv, kv...) + return &lazyLogrSink{name: s.name, values: nv} +} + +func (s *lazyLogrSink) WithName(name string) logr.LogSink { + out := s.name + if out == "" { + out = name + } else { + out = out + "." + name + } + return &lazyLogrSink{name: out, values: s.values} +} diff --git a/pkg/log/zap_test.go b/pkg/log/zap_test.go index 3da2668f2a..4f4179fe8d 100644 --- a/pkg/log/zap_test.go +++ b/pkg/log/zap_test.go @@ -3,12 +3,14 @@ package log import ( + "log/slog" "os" "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -26,9 +28,9 @@ func TestLogFileRotation(t *testing.T) { logsToPrint := 10 for i := 0; i < logsToPrint; i++ { - global.Info("test", zap.Int("i", i)) + loadGlobal().Info("test", zap.Int("i", i)) } - global.Close() + loadGlobal().Close() _, err := os.Stat(lOpts.FileName) assert.NoError(t, err, "Test log file is not found") @@ -40,7 +42,7 @@ func TestLogFileRotation(t *testing.T) { assert.NoError(t, err, "Getwd failed with err") err = filepath.Walk(p, func(path string, info os.FileInfo, err error) error { - global.Info("Filename: ", zap.String("path", path), zap.String("name", info.Name())) + loadGlobal().Info("Filename: ", zap.String("path", path), zap.String("name", info.Name())) if !info.IsDir() { if strings.HasPrefix(info.Name(), "test") && strings.HasSuffix(info.Name(), ".log") { curReplicas++ @@ -51,3 +53,67 @@ func TestLogFileRotation(t *testing.T) { assert.NoError(t, err, "Test log file walk through failed with err") assert.Equal(t, expectedReplicas, curReplicas, "Test log file replicas are not as expected on 2nd try") } + +func TestSlogHandler(t *testing.T) { + // Reset the global logger for this test + resetGlobalForTest() + + _, err := SetupZapLogger(GetDefaultLogOpts()) + require.NoError(t, err) + + handler := SlogHandler() + require.NotNil(t, handler) + + logger := slog.New(handler) + // Should not panic + logger.Info("test message from slog", "key", "value") + + // SetDefaultSlog should make slog.Default() return zap-backed logger + SetDefaultSlog() + slog.Default().Info("default slog test", "source", "TestSlogHandler") + + // SlogLogger should return a new logger + slogLogger := SlogLogger() + require.NotNil(t, slogLogger) + slogLogger.Info("from SlogLogger", "test", true) +} + +func TestSlogHandlerFallback(t *testing.T) { + // Reset global to test fallback behavior + resetGlobalForTest() + + // Without zap setup, SlogHandler should return a fallback text handler + handler := SlogHandler() + require.NotNil(t, handler) + + // Should not panic even without zap being setup + logger := slog.New(handler) + logger.Info("fallback test message", "key", "value") +} + +func TestLogrLogger(t *testing.T) { + // Reset the global logger for this test + resetGlobalForTest() + + _, err := SetupZapLogger(GetDefaultLogOpts()) + require.NoError(t, err) + + logrLogger := LogrLogger() + require.NotNil(t, logrLogger) + + // Should not panic and should log using the same format as Retina's zap logger + logrLogger.Info("test message from logr", "key", "value") + logrLogger.V(1).Info("debug message from logr", "level", 1) +} + +func TestLogrLoggerFallback(t *testing.T) { + // Reset global to test fallback behavior + resetGlobalForTest() + + // Without zap setup, LogrLogger should return a fallback logger + logrLogger := LogrLogger() + require.NotNil(t, logrLogger) + + // Should not panic even without zap being setup + logrLogger.Info("fallback logr test message", "key", "value") +} diff --git a/pkg/managers/controllermanager/controllermanager.go b/pkg/managers/controllermanager/controllermanager.go index 0ee6b46479..b5fcd86380 100644 --- a/pkg/managers/controllermanager/controllermanager.go +++ b/pkg/managers/controllermanager/controllermanager.go @@ -4,17 +4,16 @@ package controllermanager import ( "context" + "log/slog" "time" kcfg "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/controllers/cache" "github.com/microsoft/retina/pkg/enricher" - "github.com/microsoft/retina/pkg/log" pm "github.com/microsoft/retina/pkg/managers/pluginmanager" sm "github.com/microsoft/retina/pkg/managers/servermanager" "github.com/microsoft/retina/pkg/pubsub" "github.com/microsoft/retina/pkg/telemetry" - "go.uber.org/zap" "golang.org/x/sync/errgroup" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/informers" @@ -26,7 +25,7 @@ const ( ) type Controller struct { - l *log.ZapLogger + l *slog.Logger httpServer *sm.HTTPServer pluginManager *pm.PluginManager tel telemetry.Telemetry @@ -36,8 +35,10 @@ type Controller struct { enricher *enricher.Enricher } -func NewControllerManager(conf *kcfg.Config, kubeclient kubernetes.Interface, tel telemetry.Telemetry) (*Controller, error) { - cmLogger := log.Logger().Named("controller-manager") +func NewControllerManager( + conf *kcfg.Config, kubeclient kubernetes.Interface, tel telemetry.Telemetry, logger *slog.Logger, +) (*Controller, error) { + cmLogger := logger.With("module", "controller-manager") if conf.EnablePodLevel { // informer factory for pods/services @@ -48,6 +49,7 @@ func NewControllerManager(conf *kcfg.Config, kubeclient kubernetes.Interface, te pMgr, err := pm.NewPluginManager( conf, tel, + logger, ) if err != nil { return nil, err @@ -109,7 +111,12 @@ func (m *Controller) Start(ctx context.Context) { // }) if err := g.Wait(); err != nil { - m.l.Panic("Error running controller manager", zap.Error(err)) + m.l.Error("Error running controller manager", "error", err) + // Flush the slog handler before panicking so the error message is not lost + if h, ok := m.l.Handler().(interface{ Flush() error }); ok { + _ = h.Flush() + } + panic(err) } } diff --git a/pkg/managers/controllermanager/controllermanager_test.go b/pkg/managers/controllermanager/controllermanager_test.go index 841dda9dd6..7a92174967 100644 --- a/pkg/managers/controllermanager/controllermanager_test.go +++ b/pkg/managers/controllermanager/controllermanager_test.go @@ -5,6 +5,7 @@ package controllermanager import ( "context" "errors" + "log/slog" "testing" "time" @@ -33,7 +34,7 @@ func TestNewControllerManager(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) kubeclient := k8sfake.NewSimpleClientset() - cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry()) + cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry(), slog.Default()) assert.NoError(t, err, "Expected no error, instead got %+v", err) assert.NotNil(t, cm) } @@ -45,7 +46,7 @@ func TestNewControllerManagerWin(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) kubeclient := k8sfake.NewSimpleClientset() - cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry()) + cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry(), slog.Default()) assert.Error(t, err, "Expected error of not recognising windows plugins in linux, instead got no error") assert.Nil(t, cm) } @@ -57,7 +58,7 @@ func TestNewControllerManagerInit(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) kubeclient := k8sfake.NewSimpleClientset() - cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry()) + cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry(), slog.Default()) assert.NoError(t, err, "Expected no error, instead got %+v", err) assert.NotNil(t, cm) @@ -72,7 +73,7 @@ func TestControllerPluginManagerStartFail(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) kubeclient := k8sfake.NewSimpleClientset() - cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry()) + cm, err := NewControllerManager(c, kubeclient, telemetry.NewNoopTelemetry(), slog.Default()) assert.NoError(t, err, "Expected no error, instead got %+v", err) assert.NotNil(t, cm) @@ -86,7 +87,7 @@ func TestControllerPluginManagerStartFail(t *testing.T) { EnablePodLevel: true, EnabledPlugin: []string{pluginName}, } - mgr, err := pm.NewPluginManager(cfg, telemetry.NewNoopTelemetry()) + mgr, err := pm.NewPluginManager(cfg, telemetry.NewNoopTelemetry(), slog.Default()) require.NoError(t, err, "Expected no error, instead got %+v", err) mockPlugin := plugin.NewMockPlugin(ctl) diff --git a/pkg/managers/pluginmanager/cells_linux.go b/pkg/managers/pluginmanager/cells_linux.go index 5a77ef1c0b..a8e4a7ffa4 100644 --- a/pkg/managers/pluginmanager/cells_linux.go +++ b/pkg/managers/pluginmanager/cells_linux.go @@ -2,6 +2,8 @@ package pluginmanager import ( "context" + "log/slog" + "os" "sync" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" @@ -9,7 +11,6 @@ import ( "github.com/microsoft/retina/pkg/config" "github.com/microsoft/retina/pkg/metrics" "github.com/microsoft/retina/pkg/telemetry" - "github.com/sirupsen/logrus" ) const ( @@ -30,7 +31,7 @@ var Cell = cell.Module( type pluginManagerParams struct { cell.In - Log logrus.FieldLogger + Log *slog.Logger Lifecycle cell.Lifecycle Config config.Config Telemetry telemetry.Telemetry @@ -38,12 +39,12 @@ type pluginManagerParams struct { } func newPluginManager(params pluginManagerParams) (*PluginManager, error) { - logger := params.Log.WithField("module", "pluginmanager") + logger := params.Log.With("module", "plugin-manager") // Enable Metrics in retina - metrics.InitializeMetrics() + metrics.InitializeMetrics(params.Log) - pluginMgr, err := NewPluginManager(¶ms.Config, params.Telemetry) + pluginMgr, err := NewPluginManager(¶ms.Config, params.Telemetry, params.Log) if err != nil { return &PluginManager{}, err } @@ -61,7 +62,8 @@ func newPluginManager(params pluginManagerParams) (*PluginManager, error) { defer wg.Done() err = pluginMgr.Start(pmCtx) if err != nil { - logger.WithError(err).Fatal("failed to start plugin manager") + logger.Error("failed to start plugin manager", "error", err) + os.Exit(1) } }() diff --git a/pkg/managers/pluginmanager/pluginmanager.go b/pkg/managers/pluginmanager/pluginmanager.go index f3d3ad5348..f3f66a28bc 100644 --- a/pkg/managers/pluginmanager/pluginmanager.go +++ b/pkg/managers/pluginmanager/pluginmanager.go @@ -5,19 +5,18 @@ package pluginmanager import ( "context" "fmt" + "log/slog" "sync" "time" v1 "github.com/cilium/cilium/pkg/hubble/api/v1" kcfg "github.com/microsoft/retina/pkg/config" - "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/managers/watchermanager" "github.com/microsoft/retina/pkg/metrics" "github.com/microsoft/retina/pkg/plugin" "github.com/microsoft/retina/pkg/plugin/conntrack" "github.com/microsoft/retina/pkg/telemetry" "github.com/pkg/errors" - "go.uber.org/zap" "golang.org/x/sync/errgroup" ) @@ -41,18 +40,17 @@ var ( type PluginManager struct { cfg *kcfg.Config - l *log.ZapLogger + l *slog.Logger plugins map[string]plugin.Plugin tel telemetry.Telemetry watcherManager watchermanager.IWatcherManager } -func NewPluginManager(cfg *kcfg.Config, tel telemetry.Telemetry) (*PluginManager, error) { - logger := log.Logger().Named("plugin-manager") +func NewPluginManager(cfg *kcfg.Config, tel telemetry.Telemetry, logger *slog.Logger) (*PluginManager, error) { mgr := &PluginManager{ cfg: cfg, - l: logger, + l: logger.With("module", "plugin-manager"), tel: tel, plugins: map[string]plugin.Plugin{}, } @@ -82,12 +80,12 @@ func (p *PluginManager) Stop() { go func(plugin plugin.Plugin) { defer wg.Done() if err := plugin.Stop(); err != nil { - p.l.Error("failed to stop plugin", zap.Error(err)) + p.l.Error("failed to stop plugin", "error", err) // Continue stopping other plugins. // This allows us to stop as many plugins as possible, // even if some plugins fail to stop. } - p.l.Info("Cleaned up resource for plugin", zap.String("name", plugin.Name())) + p.l.Info("Cleaned up resource for plugin", "name", plugin.Name()) }(pl) } wg.Wait() @@ -113,7 +111,7 @@ func (p *PluginManager) Reconcile(ctx context.Context, pl plugin.Plugin) error { return errors.Wrap(err, "failed to init plugin") } - p.l.Info("Reconciled plugin", zap.String("name", pl.Name())) + p.l.Info("Reconciled plugin", "name", pl.Name()) return nil } @@ -129,7 +127,7 @@ func (p *PluginManager) Start(ctx context.Context) error { } if p.cfg.MetricsInterval <= 0 { - p.l.Warn("MetricsInterval is invalid or unset; defaulting to 10s", zap.Duration("interval", p.cfg.MetricsInterval)) + p.l.Warn("MetricsInterval is invalid or unset; defaulting to 10s", slog.Duration("interval", p.cfg.MetricsInterval)) p.cfg.MetricsInterval = DefaultMetricsInterval } @@ -181,7 +179,7 @@ func (p *PluginManager) Start(ctx context.Context) error { // on cancel context wait for all plugins to exit err = g.Wait() if err != nil { - p.l.Error("plugin manager exited with error", zap.Error(err)) + p.l.Error("plugin manager exited with error", "error", err) return errors.Wrapf(err, "failed to start plugin manager, plugin exited") } @@ -210,10 +208,13 @@ func (p *PluginManager) SetPlugin(name string, pl plugin.Plugin) { } func (p *PluginManager) SetupChannel(c chan *v1.Event) { + p.l.Info("Setting up external event channel for plugins", "channelCap", cap(c), "pluginCount", len(p.plugins)) for name, plugin := range p.plugins { err := plugin.SetupChannel(c) if err != nil { - p.l.Error("failed to setup channel for plugin", zap.String("plugin name", name), zap.Error(err)) + p.l.Error("failed to setup channel for plugin", "plugin name", name, "error", err) + } else { + p.l.Info("Setup channel for plugin", "plugin", name) } } } diff --git a/pkg/managers/pluginmanager/pluginmanager_test.go b/pkg/managers/pluginmanager/pluginmanager_test.go index 036cfc69c7..d5f50ee9bf 100644 --- a/pkg/managers/pluginmanager/pluginmanager_test.go +++ b/pkg/managers/pluginmanager/pluginmanager_test.go @@ -5,6 +5,7 @@ package pluginmanager import ( "context" "errors" + "log/slog" "strings" "testing" "time" @@ -83,7 +84,7 @@ func TestNewManager(t *testing.T) { for _, tt := range tests { tt.cfg.EnabledPlugin = append(tt.cfg.EnabledPlugin, tt.pluginName) - mgr, err := NewPluginManager(&tt.cfg, tel) + mgr, err := NewPluginManager(&tt.cfg, tel, slog.Default()) if tt.wantErr { require.NotNil(t, err, "Expected error but got nil") require.Nil(t, mgr, "Expected mgr to be nil but it isn't") @@ -123,7 +124,7 @@ func TestNewManagerStart(t *testing.T) { for _, tt := range tests { tt.cfg.EnabledPlugin = append(tt.cfg.EnabledPlugin, tt.pluginName) - mgr, err := NewPluginManager(&tt.cfg, tel) + mgr, err := NewPluginManager(&tt.cfg, tel, slog.Default()) require.NoError(t, err) mgr.watcherManager = setupWatcherManagerMock(gomock.NewController(t)) require.Nil(t, err, "Expected nil but got error:%w", err) @@ -172,7 +173,7 @@ func TestStart_InvalidMetricsIntervalDefaultsTo10s(t *testing.T) { cfg.MetricsInterval = tt.interval cfg.EnabledPlugin = append(cfg.EnabledPlugin, mockPluginName) - mgr, err := NewPluginManager(&cfg, telemetry.NewNoopTelemetry()) + mgr, err := NewPluginManager(&cfg, telemetry.NewNoopTelemetry(), slog.Default()) require.NoError(t, err) require.NotNil(t, mgr) mgr.watcherManager = setupWatcherManagerMock(ctl) @@ -221,7 +222,7 @@ func TestNewManagerWithPluginStartFailure(t *testing.T) { cfg := cfgPodLevelEnabled mgr := &PluginManager{ cfg: &cfg, - l: log.Logger().Named("plugin-manager"), + l: slog.Default().With("module", "plugin-manager"), plugins: make(map[string]plugin.Plugin), tel: telemetry.NewNoopTelemetry(), watcherManager: setupWatcherManagerMock(ctl), @@ -253,14 +254,14 @@ func TestNewManagerWithPluginReconcileFailure(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) pluginName := "mockplugin" cfg := cfgPodLevelEnabled mgr := &PluginManager{ cfg: &cfg, - l: log.Logger().Named("plugin-manager"), + l: slog.Default().With("module", "plugin-manager"), plugins: make(map[string]plugin.Plugin), tel: telemetry.NewNoopTelemetry(), watcherManager: setupWatcherManagerMock(ctl), @@ -317,7 +318,7 @@ func TestPluginInit(t *testing.T) { } for _, tt := range tests { tt.cfg.EnabledPlugin = append(tt.cfg.EnabledPlugin, tt.pluginName) - mgr, err := NewPluginManager(&tt.cfg, tel) + mgr, err := NewPluginManager(&tt.cfg, tel, slog.Default()) require.Nil(t, err, "Expected nil but got error:%w", err) for _, plugin := range mgr.plugins { if tt.wantErr { @@ -359,7 +360,7 @@ func TestPluginStartWithoutInit(t *testing.T) { } for _, tt := range tests { tt.cfg.EnabledPlugin = append(tt.cfg.EnabledPlugin, tt.pluginName) - mgr, err := NewPluginManager(&tt.cfg, tel) + mgr, err := NewPluginManager(&tt.cfg, tel, slog.Default()) require.Nil(t, err, "Expected nil but got error:%w", err) for _, plugin := range mgr.plugins { if tt.initPlugin { @@ -447,7 +448,7 @@ func TestPluginStop(t *testing.T) { } for _, tt := range tests { tt.cfg.EnabledPlugin = append(tt.cfg.EnabledPlugin, tt.pluginName) - mgr, err := NewPluginManager(&tt.cfg, tel) + mgr, err := NewPluginManager(&tt.cfg, tel, slog.Default()) require.Nil(t, err, "Expected nil but got error:%w", err) for _, plugin := range mgr.plugins { if tt.initPlugin { @@ -482,7 +483,7 @@ func TestStopPluginManagerGracefully(t *testing.T) { cfg := cfgPodLevelEnabled mgr := &PluginManager{ cfg: &cfg, - l: log.Logger().Named("plugin-manager"), + l: slog.Default().With("module", "plugin-manager"), plugins: make(map[string]plugin.Plugin), tel: telemetry.NewNoopTelemetry(), watcherManager: setupWatcherManagerMock(ctl), @@ -522,7 +523,7 @@ func TestWatcherManagerFailure(t *testing.T) { cfg := cfgPodLevelEnabled mgr := &PluginManager{ cfg: &cfg, - l: log.Logger().Named("plugin-manager"), + l: slog.Default().With("module", "plugin-manager"), plugins: make(map[string]plugin.Plugin), tel: telemetry.NewNoopTelemetry(), watcherManager: m, diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index c40c2c39da..d0f62df14b 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -3,16 +3,20 @@ package metrics import ( + "log/slog" + "github.com/microsoft/retina/pkg/exporter" - "github.com/microsoft/retina/pkg/log" "github.com/microsoft/retina/pkg/utils" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" ) // Initiates and creates the common metrics -func InitializeMetrics() { - metricsLogger = log.Logger().Named("metrics") +func InitializeMetrics(logger *slog.Logger) { + if logger == nil { + logger = slog.Default() + } + metricsLogger = logger.With("module", "metrics") if isInitialized { metricsLogger.Warn("Metrics already initialized. Exiting.") diff --git a/pkg/metrics/metrics_test.go b/pkg/metrics/metrics_test.go index 10a8d8012d..26514e7283 100644 --- a/pkg/metrics/metrics_test.go +++ b/pkg/metrics/metrics_test.go @@ -4,6 +4,7 @@ package metrics import ( + "log/slog" "testing" "github.com/microsoft/retina/pkg/log" @@ -12,7 +13,7 @@ import ( func TestInitialization_FirstInit(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) - InitializeMetrics() + InitializeMetrics(slog.Default()) // All metrics should be initialized. objs := []interface{}{DropPacketsGauge, DropBytesGauge, ForwardBytesGauge, ForwardPacketsGauge, NodeConnectivityStatusGauge, NodeConnectivityLatencyGauge, PluginManagerFailedToReconcileCounter} @@ -31,7 +32,7 @@ func TestInitialization_MultipleInit(t *testing.T) { }() log.SetupZapLogger(log.GetDefaultLogOpts()) - InitializeMetrics() + InitializeMetrics(slog.Default()) // Should not panic when reinitializing. - InitializeMetrics() + InitializeMetrics(slog.Default()) } diff --git a/pkg/metrics/types.go b/pkg/metrics/types.go index cbc76f46ad..54f8446bb5 100644 --- a/pkg/metrics/types.go +++ b/pkg/metrics/types.go @@ -3,9 +3,9 @@ package metrics import ( - "github.com/microsoft/retina/pkg/log" + "log/slog" + "github.com/prometheus/client_golang/prometheus" - "go.uber.org/zap" ) const ( @@ -89,7 +89,7 @@ var ( // Interface Stats InterfaceStatsGauge GaugeVec - metricsLogger *log.ZapLogger + metricsLogger *slog.Logger // Control Plane Metrics PluginManagerFailedToReconcileCounter CounterVec @@ -122,7 +122,9 @@ func ToPrometheusType(metric interface{}) prometheus.Collector { case CounterVec: return m.(*prometheus.CounterVec) default: - metricsLogger.Error("error converting unknown metric type", zap.Any("metric", m)) + if metricsLogger != nil { + metricsLogger.Error("error converting unknown metric type", slog.Any("metric", m)) + } return nil } } diff --git a/pkg/module/metrics/dns_test.go b/pkg/module/metrics/dns_test.go index 4ada8ff21d..7bf582139c 100644 --- a/pkg/module/metrics/dns_test.go +++ b/pkg/module/metrics/dns_test.go @@ -4,6 +4,7 @@ package metrics import ( + "log/slog" "reflect" "testing" "time" @@ -305,7 +306,7 @@ func TestProcessLocalCtx(t *testing.T) { assert.Equal(t, 0, len(d.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite") // Test TTL based expiration - metricsinit.InitializeMetrics() + metricsinit.InitializeMetrics(slog.Default()) // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics d = NewDNSMetrics(ctxOptions, l, localContext, time.Minute) diff --git a/pkg/module/metrics/drops_test.go b/pkg/module/metrics/drops_test.go index 2f8650af5d..b6774fae04 100644 --- a/pkg/module/metrics/drops_test.go +++ b/pkg/module/metrics/drops_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" "go.uber.org/zap" + "log/slog" ) func TestNewDrop(t *testing.T) { @@ -308,7 +309,7 @@ func TestNewDrop(t *testing.T) { assert.Equal(t, 0, len(f.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite Test Name: %s", tc.name) // Test TTL based expiration - metricsinit.InitializeMetrics() + metricsinit.InitializeMetrics(slog.Default()) // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics f = NewDropCountMetrics(tc.opts, log.Logger(), tc.localContext, time.Minute) diff --git a/pkg/module/metrics/forward_test.go b/pkg/module/metrics/forward_test.go index 0c616c79b6..e1a94c0314 100644 --- a/pkg/module/metrics/forward_test.go +++ b/pkg/module/metrics/forward_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" "go.uber.org/zap" + "log/slog" ) type TestMetrics struct { @@ -346,7 +347,7 @@ func TestNewForward(t *testing.T) { assert.Equal(t, 0, len(f.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite Test Name: %s", tc.name) // Test TTL based expiration - metricsinit.InitializeMetrics() + metricsinit.InitializeMetrics(slog.Default()) // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics f = NewForwardCountMetrics(tc.opts, log.Logger(), tc.localContext, time.Minute) diff --git a/pkg/module/metrics/tcpflags_test.go b/pkg/module/metrics/tcpflags_test.go index 16ad91a326..9be4e15b00 100644 --- a/pkg/module/metrics/tcpflags_test.go +++ b/pkg/module/metrics/tcpflags_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" "go.uber.org/zap" + "log/slog" ) func TestNewTCPMetrics(t *testing.T) { @@ -503,7 +504,7 @@ func TestNewTCPMetrics(t *testing.T) { assert.Equal(t, 0, len(tcp.trackedMetricLabels()), "there should be no tracked metrics when TTL is infinite Test Name: %s", tc.name) // Test TTL based expiration - metricsinit.InitializeMetrics() + metricsinit.InitializeMetrics(slog.Default()) // Set the TTL to something high to ensure that our call to expire is the only one that expires the metrics tcp = NewTCPMetrics(tc.opts, log.Logger(), tc.localContext, time.Minute) diff --git a/pkg/monitoragent/cell_linux.go b/pkg/monitoragent/cell_linux.go index 9a9055d09a..5a0f9dc720 100644 --- a/pkg/monitoragent/cell_linux.go +++ b/pkg/monitoragent/cell_linux.go @@ -2,16 +2,17 @@ package monitoragent import ( "context" + "log/slog" + "sync" "github.com/cilium/cilium/pkg/defaults" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" ciliumagent "github.com/cilium/cilium/pkg/monitor/agent" "github.com/cilium/cilium/pkg/monitor/agent/consumer" "github.com/cilium/cilium/pkg/monitor/agent/listener" "github.com/cilium/ebpf" "github.com/cilium/hive/cell" - "github.com/sirupsen/logrus" + retinalog "github.com/microsoft/retina/pkg/log" "github.com/spf13/pflag" ) @@ -24,9 +25,19 @@ var ( cell.Config(defaultConfig), ) - log = logging.DefaultLogger.WithField(logfields.LogSubsys, "monitor-agent") + logOnce sync.Once + cachedLog *slog.Logger ) +// log returns a zap-backed slog logger. Resolved lazily so that SetupZapLogger +// (run at program startup, after package init) is the source. +func log() *slog.Logger { + logOnce.Do(func() { + cachedLog = retinalog.SlogLogger().With(logfields.LogSubsys, "monitor-agent") + }) + return cachedLog +} + type AgentConfig struct { // EnableMonitor enables the monitor unix domain socket server EnableMonitor bool @@ -48,7 +59,6 @@ type agentParams struct { cell.In Lifecycle cell.Lifecycle - Log logrus.FieldLogger Config AgentConfig } diff --git a/pkg/monitoragent/monitoragent_linux.go b/pkg/monitoragent/monitoragent_linux.go index 757e4a9ac1..c171ee82e3 100644 --- a/pkg/monitoragent/monitoragent_linux.go +++ b/pkg/monitoragent/monitoragent_linux.go @@ -13,7 +13,6 @@ import ( "github.com/cilium/cilium/pkg/monitor/agent/listener" "github.com/cilium/cilium/pkg/monitor/api" "github.com/cilium/cilium/pkg/monitor/payload" - "github.com/sirupsen/logrus" ) var ( @@ -107,7 +106,7 @@ func (a *monitorAgent) RegisterNewListener(newListener listener.MonitorListener) defer a.Unlock() if isCtxDone(a.ctx) { - log.Debug("RegisterNewListener called on stopped monitor") + log().Debug("RegisterNewListener called on stopped monitor") newListener.Close() return } @@ -118,13 +117,13 @@ func (a *monitorAgent) RegisterNewListener(newListener listener.MonitorListener) a.listeners[newListener] = struct{}{} default: newListener.Close() - log.WithField("version", version).Error("Closing listener from unsupported monitor client version") + log().Error("Closing listener from unsupported monitor client version", "version", version) } - log.WithFields(logrus.Fields{ - "count.listener": len(a.listeners), - "version": version, - }).Debug("New listener connected") + log().Debug("New listener connected", + "count.listener", len(a.listeners), + "version", version, + ) } func (a *monitorAgent) RemoveListener(ml listener.MonitorListener) { @@ -137,20 +136,23 @@ func (a *monitorAgent) RemoveListener(ml listener.MonitorListener) { // Remove the listener and close it. delete(a.listeners, ml) - log.WithFields(logrus.Fields{ - "count.listener": len(a.listeners), - "version": ml.Version(), - }).Debug("Removed listener") + log().Debug("Removed listener", + "count.listener", len(a.listeners), + "version", ml.Version(), + ) ml.Close() } func (a *monitorAgent) RegisterNewConsumer(newConsumer consumer.MonitorConsumer) { if a == nil || newConsumer == nil { + log().Info("RegisterNewConsumer called with nil agent or consumer", + "agentNil", a == nil, + "consumerNil", newConsumer == nil) return } if isCtxDone(a.ctx) { - log.Debug("RegisterNewConsumer called on stopped monitor") + log().Debug("RegisterNewConsumer called on stopped monitor") return } @@ -158,6 +160,9 @@ func (a *monitorAgent) RegisterNewConsumer(newConsumer consumer.MonitorConsumer) defer a.Unlock() a.consumers[newConsumer] = struct{}{} + log().Info("Registered new consumer with monitor agent", + "consumerCount", len(a.consumers), + "consumerType", fmt.Sprintf("%T", newConsumer)) } func (a *monitorAgent) RemoveConsumer(mc consumer.MonitorConsumer) { @@ -207,8 +212,7 @@ func (a *monitorAgent) sendToListenersLocked(pl *payload.Payload) { } } -// notifyAgentEvent notifies all consumers about an agent event. -func (a *monitorAgent) notifyAgentEvent(typ int, message interface{}) { +func (a *monitorAgent) notifyAgentEvent(typ int, message any) { a.Lock() defer a.Unlock() for mc := range a.consumers { diff --git a/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go b/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go index ec0dc6c1e2..b0b4f53053 100644 --- a/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go +++ b/pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go @@ -4,6 +4,7 @@ package ciliumeventobserver import ( "context" "errors" + "log/slog" "net" "testing" "time" @@ -18,6 +19,7 @@ import ( "github.com/microsoft/retina/pkg/controllers/cache" "github.com/microsoft/retina/pkg/enricher" "github.com/microsoft/retina/pkg/log" + "github.com/microsoft/retina/pkg/metrics" "github.com/microsoft/retina/pkg/pubsub" "gotest.tools/assert" ) @@ -109,6 +111,7 @@ func TestMonitorLoop(t *testing.T) { func TestParse(t *testing.T) { ctxWithCancel, cancel := context.WithCancel(context.Background()) _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + metrics.InitializeMetrics(slog.Default()) cfg := &config.Config{ EnablePodLevel: true, } diff --git a/pkg/plugin/ciliumeventobserver/parser_linux.go b/pkg/plugin/ciliumeventobserver/parser_linux.go index e653c99c6f..cbf3b2d7e8 100644 --- a/pkg/plugin/ciliumeventobserver/parser_linux.go +++ b/pkg/plugin/ciliumeventobserver/parser_linux.go @@ -30,7 +30,6 @@ func (p *parser) Init() error { &hptestutils.NoopServiceGetter, &hptestutils.NoopLinkGetter, &hptestutils.NoopPodMetadataGetter, - true, ) if err != nil { p.l.Fatal("Failed to create parser", zap.Error(err)) diff --git a/pkg/plugin/common/common_linux.go b/pkg/plugin/common/common_linux.go index b666066028..2c7e196c5e 100644 --- a/pkg/plugin/common/common_linux.go +++ b/pkg/plugin/common/common_linux.go @@ -22,18 +22,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run go.uber.org/mock/mockgen@v0.4.0 -destination=mocks/mock_types.go -package=mocks . ITracer - -// Interface for IG tracers. -// Ref: https://pkg.go.dev/github.com/inspektor-gadget/inspektor-gadget@v0.18.1/pkg/gadgets/trace/dns/tracer#Tracer -type ITracer interface { - SetEventHandler(interface{}) - Attach(pid uint32) error - Detach(pid uint32) error - Close() -} - -// Interface for IG event handlers. Maps to cilum Flow. +// ProtocolToFlow converts a protocol string to the corresponding Unix protocol number. func ProtocolToFlow(protocol string) int { switch protocol { case "tcp": diff --git a/pkg/plugin/common/mocks/mock_types.go b/pkg/plugin/common/mocks/mock_types.go deleted file mode 100644 index 700efb176e..0000000000 --- a/pkg/plugin/common/mocks/mock_types.go +++ /dev/null @@ -1,91 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/microsoft/retina/pkg/plugin/common (interfaces: ITracer) -// -// Generated by this command: -// -// mockgen -destination=mocks/mock_types.go -package=mocks . ITracer -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gomock "go.uber.org/mock/gomock" -) - -// MockITracer is a mock of ITracer interface. -type MockITracer struct { - ctrl *gomock.Controller - recorder *MockITracerMockRecorder -} - -// MockITracerMockRecorder is the mock recorder for MockITracer. -type MockITracerMockRecorder struct { - mock *MockITracer -} - -// NewMockITracer creates a new mock instance. -func NewMockITracer(ctrl *gomock.Controller) *MockITracer { - mock := &MockITracer{ctrl: ctrl} - mock.recorder = &MockITracerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockITracer) EXPECT() *MockITracerMockRecorder { - return m.recorder -} - -// Attach mocks base method. -func (m *MockITracer) Attach(arg0 uint32) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Attach", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// Attach indicates an expected call of Attach. -func (mr *MockITracerMockRecorder) Attach(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Attach", reflect.TypeOf((*MockITracer)(nil).Attach), arg0) -} - -// Close mocks base method. -func (m *MockITracer) Close() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Close") -} - -// Close indicates an expected call of Close. -func (mr *MockITracerMockRecorder) Close() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockITracer)(nil).Close)) -} - -// Detach mocks base method. -func (m *MockITracer) Detach(arg0 uint32) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Detach", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// Detach indicates an expected call of Detach. -func (mr *MockITracerMockRecorder) Detach(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Detach", reflect.TypeOf((*MockITracer)(nil).Detach), arg0) -} - -// SetEventHandler mocks base method. -func (m *MockITracer) SetEventHandler(arg0 any) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetEventHandler", arg0) -} - -// SetEventHandler indicates an expected call of SetEventHandler. -func (mr *MockITracerMockRecorder) SetEventHandler(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetEventHandler", reflect.TypeOf((*MockITracer)(nil).SetEventHandler), arg0) -} diff --git a/pkg/plugin/dns/dns_linux_test.go b/pkg/plugin/dns/dns_linux_test.go index ea10ee1e36..92a3574c80 100644 --- a/pkg/plugin/dns/dns_linux_test.go +++ b/pkg/plugin/dns/dns_linux_test.go @@ -5,6 +5,7 @@ package dns import ( "context" + "log/slog" "net" "os" "testing" @@ -26,7 +27,7 @@ import ( func TestMain(m *testing.M) { log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) os.Exit(m.Run()) } diff --git a/pkg/plugin/dropreason/dropreason_linux_test.go b/pkg/plugin/dropreason/dropreason_linux_test.go index b57924901a..0b39bfdfb7 100644 --- a/pkg/plugin/dropreason/dropreason_linux_test.go +++ b/pkg/plugin/dropreason/dropreason_linux_test.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "log/slog" "os" "path" "reflect" @@ -121,7 +122,7 @@ func TestCompile(t *testing.T) { func TestProcessMapValue(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) dr := &dropReason{ cfg: cfgPodLevelEnabled, l: log.Logger().Named(name), diff --git a/pkg/plugin/packetforward/packetforward_linux_test.go b/pkg/plugin/packetforward/packetforward_linux_test.go index 2393889ee4..de727cf82d 100644 --- a/pkg/plugin/packetforward/packetforward_linux_test.go +++ b/pkg/plugin/packetforward/packetforward_linux_test.go @@ -10,6 +10,7 @@ import ( "context" "errors" "fmt" + "log/slog" "os" "testing" "time" @@ -181,7 +182,7 @@ func TestShutdown(t *testing.T) { func TestRun(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -214,7 +215,7 @@ func TestRun(t *testing.T) { func TestRun_ReturnError_Ingress(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -247,7 +248,7 @@ func TestRun_ReturnError_Ingress(t *testing.T) { func TestRun_ReturnError_Egress(t *testing.T) { log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctrl := gomock.NewController(t) defer ctrl.Finish() diff --git a/pkg/plugin/tcpretrans/tcpretrans_linux_test.go b/pkg/plugin/tcpretrans/tcpretrans_linux_test.go index f6cca3891c..75c965fee0 100644 --- a/pkg/plugin/tcpretrans/tcpretrans_linux_test.go +++ b/pkg/plugin/tcpretrans/tcpretrans_linux_test.go @@ -4,6 +4,7 @@ package tcpretrans import ( + "log/slog" "net" "os" "testing" @@ -22,7 +23,7 @@ import ( func TestMain(m *testing.M) { _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) os.Exit(m.Run()) } diff --git a/pkg/servermanager/cell_linux.go b/pkg/servermanager/cell_linux.go index 5ab934284f..237df90479 100644 --- a/pkg/servermanager/cell_linux.go +++ b/pkg/servermanager/cell_linux.go @@ -3,12 +3,12 @@ package servermanager import ( "context" "fmt" + "log/slog" "sync" "github.com/cilium/hive/cell" "github.com/microsoft/retina/pkg/config" sm "github.com/microsoft/retina/pkg/managers/servermanager" - "github.com/sirupsen/logrus" ) var Cell = cell.Module( @@ -20,18 +20,18 @@ var Cell = cell.Module( type serverParams struct { cell.In - Log logrus.FieldLogger + Log *slog.Logger Lifecycle cell.Lifecycle Config config.Config } func newServerManager(params serverParams) (*sm.HTTPServer, error) { - logger := params.Log.WithField("module", "servermanager") + logger := params.Log.With("module", "servermanager") serverCtx, cancelCtx := context.WithCancel(context.Background()) serverManager := sm.NewHTTPServer(params.Config.APIServer.Host, params.Config.APIServer.Port) if err := serverManager.Init(); err != nil { - logger.WithError(err).Error("Unable to initialize Http server") + logger.Error("Unable to initialize Http server", "error", err) cancelCtx() return nil, fmt.Errorf("unable to initialize Http server: %w", err) } @@ -43,7 +43,7 @@ func newServerManager(params serverParams) (*sm.HTTPServer, error) { go func() { defer wg.Done() if err := serverManager.Start(serverCtx); err != nil { - logger.WithError(err).Error("Unable to start server") + logger.Error("Unable to start server", "error", err) } }() diff --git a/pkg/shared/telemetry/cell_linux.go b/pkg/shared/telemetry/cell_linux.go index a43b4df8d1..f4561116e6 100644 --- a/pkg/shared/telemetry/cell_linux.go +++ b/pkg/shared/telemetry/cell_linux.go @@ -3,12 +3,12 @@ package telemetry import ( "context" "fmt" + "log/slog" "strings" "time" "github.com/cilium/hive/cell" "github.com/microsoft/retina/pkg/telemetry" - "github.com/sirupsen/logrus" "k8s.io/client-go/rest" ) @@ -34,11 +34,11 @@ var ( Constructor = cell.Module( "telemetry", "provides telemetry", - cell.Provide(func(p params, l logrus.FieldLogger) (telemetry.Telemetry, error) { - l.WithFields(logrus.Fields{ - "app-insights-id": p.Config.ApplicationInsightsID, - "retina-version": p.Config.RetinaVersion, - }).Info("configuring telemetry") + cell.Provide(func(p params, l *slog.Logger) (telemetry.Telemetry, error) { + l.Info("configuring telemetry", + "app-insights-id", p.Config.ApplicationInsightsID, + "retina-version", p.Config.RetinaVersion, + ) if p.Config.EnableTelemetry { if p.Config.ApplicationInsightsID == "" { @@ -75,7 +75,7 @@ var ( "heartbeat", "sends periodic telemetry heartbeat", cell.Invoke( - func(tel telemetry.Telemetry, lifecycle cell.Lifecycle, l logrus.FieldLogger) { + func(tel telemetry.Telemetry, lifecycle cell.Lifecycle, l *slog.Logger) { ctx, cancelCtx := context.WithCancel(context.Background()) lifecycle.Append(cell.Hook{ OnStart: func(cell.HookContext) error { diff --git a/pkg/utils/flow_utils.go b/pkg/utils/flow_utils.go index 73a196bded..6d3da9c243 100644 --- a/pkg/utils/flow_utils.go +++ b/pkg/utils/flow_utils.go @@ -16,13 +16,6 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -// Additional Verdicts to be used for flow objects -const ( - Verdict_RETRANSMISSION flow.Verdict = 15 - Verdict_DNS flow.Verdict = 16 - TypeUrl string = "retina.sh" -) - // Extension field keys for structpb.Struct const ( ExtKeyBytes = "bytes" @@ -39,6 +32,13 @@ const ( zoneUnknown = "unknown" ) +// Additional Verdicts to be used for flow objects +const ( + Verdict_RETRANSMISSION flow.Verdict = 15 //nolint:revive,stylecheck // existing API, renaming would break callers + Verdict_DNS flow.Verdict = 16 //nolint:revive,stylecheck // existing API, renaming would break callers + TypeUrl string = "retina.sh" //nolint:revive,stylecheck // existing API, renaming would break callers +) + // ToFlow returns a flow.Flow object. // This sets up a L3/L4 flow object. // sourceIP, destIP are IPv4 or IPv6 addresses; IpVersion is derived from the @@ -212,7 +212,7 @@ func AddPreviouslyObservedTCPFlags(s *structpb.Struct, syn, ack, fin, rst, psh, CWR: structpb.NewNumberValue(float64(cwr)), NS: structpb.NewNumberValue(float64(ns)), }} - s.Fields[ExtKeyPrevObservedTCPFlags] = structpb.NewStructValue(tcpFlags) + s.GetFields()[ExtKeyPrevObservedTCPFlags] = structpb.NewStructValue(tcpFlags) } func PreviouslyObservedTCPFlags(f *flow.Flow) map[string]uint32 { @@ -236,7 +236,7 @@ func AddPreviouslyObservedBytes(s *structpb.Struct, bytes uint32) { if s == nil || bytes == 0 { return } - s.Fields[ExtKeyPrevObservedBytes] = structpb.NewNumberValue(float64(bytes)) + s.GetFields()[ExtKeyPrevObservedBytes] = structpb.NewNumberValue(float64(bytes)) } func PreviouslyObservedBytes(f *flow.Flow) uint32 { @@ -256,7 +256,7 @@ func AddPreviouslyObservedPackets(s *structpb.Struct, packets uint32) { if s == nil || packets == 0 { return } - s.Fields[ExtKeyPrevObservedPackets] = structpb.NewNumberValue(float64(packets)) + s.GetFields()[ExtKeyPrevObservedPackets] = structpb.NewNumberValue(float64(packets)) } func PreviouslyObservedPackets(f *flow.Flow) uint32 { @@ -293,7 +293,7 @@ func AddTCPID(s *structpb.Struct, id uint64) { if s == nil || id == 0 { return } - s.Fields[ExtKeyTCPID] = structpb.NewNumberValue(float64(id)) + s.GetFields()[ExtKeyTCPID] = structpb.NewNumberValue(float64(id)) } func GetTCPID(f *flow.Flow) uint64 { @@ -312,7 +312,10 @@ func GetTCPID(f *flow.Flow) uint64 { } // AddDNSInfo adds DNS information to the flow and its extensions. -func AddDNSInfo(f *flow.Flow, s *structpb.Struct, qType string, rCode uint32, query string, qTypes []string, numAnswers int, ips []string) { +func AddDNSInfo( + f *flow.Flow, s *structpb.Struct, qType string, rCode uint32, + query string, qTypes []string, numAnswers int, ips []string, +) { if f == nil || s == nil { return } @@ -335,17 +338,17 @@ func AddDNSInfo(f *flow.Flow, s *structpb.Struct, qType string, rCode uint32, qu } switch qType { case "Q": - s.Fields[ExtKeyDNSType] = structpb.NewStringValue(DNSType_QUERY.String()) + s.GetFields()[ExtKeyDNSType] = structpb.NewStringValue(DNSType_QUERY.String()) f.L7.Type = flow.L7FlowType_REQUEST case "R": - s.Fields[ExtKeyDNSType] = structpb.NewStringValue(DNSType_RESPONSE.String()) + s.GetFields()[ExtKeyDNSType] = structpb.NewStringValue(DNSType_RESPONSE.String()) f.L7.Type = flow.L7FlowType_RESPONSE f.IsReply = &wrapperspb.BoolValue{Value: true} // we can definitely say that this is a reply default: f.L7.Type = flow.L7FlowType_UNKNOWN_L7_TYPE } if numAnswers > 0 { - s.Fields[ExtKeyNumResponses] = structpb.NewNumberValue(float64(numAnswers)) + s.GetFields()[ExtKeyNumResponses] = structpb.NewNumberValue(float64(numAnswers)) } } @@ -405,7 +408,7 @@ func AddPacketSize(s *structpb.Struct, packetSize uint32) { if s == nil || packetSize == 0 { return } - s.Fields[ExtKeyBytes] = structpb.NewNumberValue(float64(packetSize)) + s.GetFields()[ExtKeyBytes] = structpb.NewNumberValue(float64(packetSize)) } func PacketSize(f *flow.Flow) uint32 { @@ -427,7 +430,7 @@ func AddDropReason(f *flow.Flow, s *structpb.Struct, dropReason uint16) { } dr := DropReason(dropReason) - s.Fields[ExtKeyDropReason] = structpb.NewStringValue(dr.String()) + s.GetFields()[ExtKeyDropReason] = structpb.NewStringValue(dr.String()) f.Verdict = flow.Verdict_DROPPED @@ -475,8 +478,8 @@ func AddZones(s *structpb.Struct, srcZone, dstZone string) { if s == nil { return } - s.Fields[ExtKeySourceZone] = structpb.NewStringValue(srcZone) - s.Fields[ExtKeyDestinationZone] = structpb.NewStringValue(dstZone) + s.GetFields()[ExtKeySourceZone] = structpb.NewStringValue(srcZone) + s.GetFields()[ExtKeyDestinationZone] = structpb.NewStringValue(dstZone) } // SourceZone returns the source availability zone from the flow's extensions. diff --git a/pkg/utils/testutil/cilium/endpoint_client.go b/pkg/utils/testutil/cilium/endpoint_client.go index dc57a5e240..df5d961620 100644 --- a/pkg/utils/testutil/cilium/endpoint_client.go +++ b/pkg/utils/testutil/cilium/endpoint_client.go @@ -6,8 +6,7 @@ import ( "context" "encoding/json" "fmt" - - "github.com/sirupsen/logrus" + "log/slog" v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" ciliumv2 "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned/typed/cilium.io/v2" @@ -21,13 +20,15 @@ import ( var _ ciliumv2.CiliumEndpointInterface = &MockEndpointClient{} type MockEndpointClient struct { - l logrus.FieldLogger + l *slog.Logger namespace string ciliumEndpoints *MockResource[*v2.CiliumEndpoint] watchers []watch.Interface } -func NewMockEndpointClient(l logrus.FieldLogger, namespace string, ciliumEndpoints *MockResource[*v2.CiliumEndpoint]) *MockEndpointClient { +func NewMockEndpointClient( + l *slog.Logger, namespace string, ciliumEndpoints *MockResource[*v2.CiliumEndpoint], +) *MockEndpointClient { return &MockEndpointClient{ l: l, namespace: namespace, diff --git a/pkg/utils/testutil/cilium/identity_client.go b/pkg/utils/testutil/cilium/identity_client.go index 625c990c81..b0aa3bc45d 100644 --- a/pkg/utils/testutil/cilium/identity_client.go +++ b/pkg/utils/testutil/cilium/identity_client.go @@ -4,13 +4,12 @@ package ciliumutil import ( "context" + "log/slog" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/watch" - "github.com/sirupsen/logrus" - v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" ciliumv2 "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned/typed/cilium.io/v2" ) @@ -23,14 +22,14 @@ var _ ciliumv2.CiliumIdentityInterface = &MockIdentityClient{} // - CRDBackend within the Allocator within the IdentityManager // - identitygc cell type MockIdentityClient struct { - l logrus.FieldLogger + l *slog.Logger // identities maps identity name to identity // namespace is irrelevant since identity names must be globally unique numbers identities map[string]*v2.CiliumIdentity watchers []watch.Interface } -func NewMockIdentityClient(l logrus.FieldLogger) *MockIdentityClient { +func NewMockIdentityClient(l *slog.Logger) *MockIdentityClient { return &MockIdentityClient{ l: l, identities: make(map[string]*v2.CiliumIdentity), diff --git a/pkg/utils/testutil/cilium/resource.go b/pkg/utils/testutil/cilium/resource.go index fa2e4d3a08..f56d8bc815 100644 --- a/pkg/utils/testutil/cilium/resource.go +++ b/pkg/utils/testutil/cilium/resource.go @@ -4,9 +4,9 @@ package ciliumutil import ( "context" + "log/slog" "github.com/pkg/errors" - "github.com/sirupsen/logrus" k8sRuntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/cache" @@ -28,12 +28,12 @@ var ( // i.e. Store() and GetByKey() // plus some helpers to add/remove items from the cache and error on the next call to Store() type MockResource[T k8sRuntime.Object] struct { - l logrus.FieldLogger + l *slog.Logger cache map[resource.Key]T shouldFailNextStoreCall bool } -func NewMockResource[T k8sRuntime.Object](l logrus.FieldLogger) *MockResource[T] { +func NewMockResource[T k8sRuntime.Object](l *slog.Logger) *MockResource[T] { return &MockResource[T]{ l: l, cache: make(map[resource.Key]T), diff --git a/pkg/utils/testutil/cilium/versioned_client.go b/pkg/utils/testutil/cilium/versioned_client.go index 7e29c0e92b..40bf3a49c1 100644 --- a/pkg/utils/testutil/cilium/versioned_client.go +++ b/pkg/utils/testutil/cilium/versioned_client.go @@ -3,7 +3,7 @@ package ciliumutil import ( - "github.com/sirupsen/logrus" + "log/slog" "k8s.io/client-go/rest" @@ -23,11 +23,11 @@ var ( // MockVersionedClient is a mock implementation of versioned.Interface // Currently it only returns a real value for CiliumV2() type MockVersionedClient struct { - l logrus.FieldLogger + l *slog.Logger c *MockCiliumV2Client } -func NewMockVersionedClient(l logrus.FieldLogger, ciliumEndpoints *MockResource[*v2.CiliumEndpoint]) *MockVersionedClient { +func NewMockVersionedClient(l *slog.Logger, ciliumEndpoints *MockResource[*v2.CiliumEndpoint]) *MockVersionedClient { return &MockVersionedClient{ l: l, c: NewMockCiliumV2Client(l, ciliumEndpoints), @@ -52,12 +52,12 @@ func (m *MockVersionedClient) CiliumV2alpha1() ciliumv2alpha1.CiliumV2alpha1Inte // MockCiliumV2Client is a mock implementation of ciliumv2.CiliumV2Interface. // Currently it only returns a real value for CiliumIdentities() type MockCiliumV2Client struct { - l logrus.FieldLogger + l *slog.Logger identitiyClient *MockIdentityClient ciliumEndpoints *MockResource[*v2.CiliumEndpoint] } -func NewMockCiliumV2Client(l logrus.FieldLogger, ciliumEndpoints *MockResource[*v2.CiliumEndpoint]) *MockCiliumV2Client { +func NewMockCiliumV2Client(l *slog.Logger, ciliumEndpoints *MockResource[*v2.CiliumEndpoint]) *MockCiliumV2Client { return &MockCiliumV2Client{ l: l, identitiyClient: NewMockIdentityClient(l), @@ -144,3 +144,13 @@ func (m *MockCiliumV2Client) CiliumBGPPeerConfigs() ciliumv2.CiliumBGPPeerConfig m.l.Warn("MockCiliumV2Client.CiliumNetworkPoliciesForCRD() called but this returns nil because it's not implemented") return nil } + +func (m *MockCiliumV2Client) CiliumCIDRGroups() ciliumv2.CiliumCIDRGroupInterface { + m.l.Warn("MockCiliumV2Client.CiliumCIDRGroups() called but this returns nil because it's not implemented") + return nil +} + +func (m *MockCiliumV2Client) CiliumLoadBalancerIPPools() ciliumv2.CiliumLoadBalancerIPPoolInterface { + m.l.Warn("MockCiliumV2Client.CiliumLoadBalancerIPPools() called but this returns nil because it's not implemented") + return nil +} diff --git a/pkg/utils/utils_linux_test.go b/pkg/utils/utils_linux_test.go index a142ddf102..1fecf2f7a4 100644 --- a/pkg/utils/utils_linux_test.go +++ b/pkg/utils/utils_linux_test.go @@ -47,8 +47,6 @@ func TestToFlow(t *testing.T) { assert.EqualValues(t, f.GetL4().Protocol.(*flow.Layer4_TCP).TCP.SourcePort, uint32(443)) assert.EqualValues(t, f.GetL4().Protocol.(*flow.Layer4_TCP).TCP.DestinationPort, uint32(80)) assert.NotNil(t, f.Time) - // Extensions are now set separately via SetExtensions() after populating extension fields - assert.Nil(t, f.Extensions) assert.Equal(t, f.Type, flow.FlowType_L3_L4) if !f.GetTime().IsValid() { diff --git a/test/managers/filtermanager/main.go b/test/managers/filtermanager/main.go index e2cf604dda..919500e15d 100644 --- a/test/managers/filtermanager/main.go +++ b/test/managers/filtermanager/main.go @@ -8,6 +8,7 @@ import ( "bufio" "context" "fmt" + "log/slog" "net" "os" "strings" @@ -33,7 +34,7 @@ func main() { log.SetupZapLogger(opts) l := log.Logger().Named("test-packetparser") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctx := context.Background() diff --git a/test/plugin/dns/main_linux.go b/test/plugin/dns/main_linux.go index 59cb24f50f..d225de580b 100644 --- a/test/plugin/dns/main_linux.go +++ b/test/plugin/dns/main_linux.go @@ -17,6 +17,7 @@ package main import ( "context" + "log/slog" "time" "github.com/microsoft/retina/pkg/config" @@ -35,7 +36,7 @@ func main() { log.SetupZapLogger(opts) l := log.Logger().Named("test-dns") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctx := context.Background() tt := dns.New(&config.Config{ diff --git a/test/plugin/dropreason/main_linux.go b/test/plugin/dropreason/main_linux.go index 189ffbaec7..f1c0ee40e1 100644 --- a/test/plugin/dropreason/main_linux.go +++ b/test/plugin/dropreason/main_linux.go @@ -4,6 +4,7 @@ package main import ( "context" + "log/slog" "net" "time" @@ -23,7 +24,7 @@ func main() { log.SetupZapLogger(opts) l := log.Logger().Named("test-dropreason") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() diff --git a/test/plugin/infiniband/main_linux.go b/test/plugin/infiniband/main_linux.go index 761d70854c..68f1fb4074 100644 --- a/test/plugin/infiniband/main_linux.go +++ b/test/plugin/infiniband/main_linux.go @@ -4,6 +4,7 @@ package main import ( "context" + "log/slog" "time" kcfg "github.com/microsoft/retina/pkg/config" @@ -17,7 +18,7 @@ func main() { log.SetupZapLogger(log.GetDefaultLogOpts()) //nolint std. l := log.Logger().Named("test-infiniband") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) cfg := &kcfg.Config{ MetricsInterval: 1 * time.Second, diff --git a/test/plugin/linuxutil/main_linux.go b/test/plugin/linuxutil/main_linux.go index c46dcf04a7..9de087ccc5 100644 --- a/test/plugin/linuxutil/main_linux.go +++ b/test/plugin/linuxutil/main_linux.go @@ -4,6 +4,7 @@ package main import ( "context" + "log/slog" "time" kcfg "github.com/microsoft/retina/pkg/config" @@ -19,7 +20,7 @@ func main() { log.SetupZapLogger(log.GetDefaultLogOpts()) l := log.Logger().Named("test-linuxutil") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) cfg := &kcfg.Config{ MetricsInterval: 1 * time.Second, diff --git a/test/plugin/packetforward/main_linux.go b/test/plugin/packetforward/main_linux.go index 7ace2e3570..51d20dfb59 100644 --- a/test/plugin/packetforward/main_linux.go +++ b/test/plugin/packetforward/main_linux.go @@ -6,6 +6,7 @@ package main import ( "context" + "log/slog" "time" "github.com/microsoft/retina/pkg/log" @@ -21,7 +22,7 @@ func main() { log.SetupZapLogger(log.GetDefaultLogOpts()) l := log.Logger().Named("test-packetforward") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctx := context.Background() diff --git a/test/plugin/packetparser/main_linux.go b/test/plugin/packetparser/main_linux.go index 4686437281..3ae84bfebb 100644 --- a/test/plugin/packetparser/main_linux.go +++ b/test/plugin/packetparser/main_linux.go @@ -6,6 +6,7 @@ package main import ( "context" + "log/slog" "net" "time" @@ -27,7 +28,7 @@ func main() { log.SetupZapLogger(opts) l := log.Logger().Named("test-packetparser") - metrics.InitializeMetrics() + metrics.InitializeMetrics(slog.Default()) ctxTimeout, cancel := context.WithTimeout(context.Background(), 30*time.Second) From 8ca7d3d4cf9f9680aaca78f80ee9fb01946baa30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:02:31 -0400 Subject: [PATCH 320/448] deps: bump goreleaser/goreleaser-action from 7.0.0 to 7.1.0 (#2211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 7.0.0 to 7.1.0.
Release notes

Sourced from goreleaser/goreleaser-action's releases.

v7.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/goreleaser/goreleaser-action/compare/v7...v7.1.0

Commits
  • e24998b ci: drop pre-cosign-v3 goreleaser versions from tests (#554)
  • be2e8a3 docs: document cosign verification in README (#553)
  • 5e53f8e ci: add release-major-tag workflow (#552)
  • 4068afa build: drop docker-bake in favor of plain npm (#551)
  • 213ec80 docs: add CONTRIBUTING with pre-commit workflow
  • 4b462d3 feat: verify release checksum and cosign signature (#550)
  • 01cbe07 docs: Upgrade import GPG action version (#547)
  • 2a473d7 ci(deps): bump the actions group with 5 updates (#546)
  • fdcf0b9 clean: leftover files from node 22(?)
  • 9881cc5 fix: use new static URL
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=goreleaser/goreleaser-action&package-manager=github_actions&previous-version=7.0.0&new-version=7.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index f27bb5603e..623a97951e 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -31,7 +31,7 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser build - uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 + uses: goreleaser/goreleaser-action@e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c # v7.1.0 env: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent with: @@ -55,7 +55,7 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser release - uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 + uses: goreleaser/goreleaser-action@e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c # v7.1.0 with: distribution: goreleaser version: latest From 9df248a096b81212f3b1164c25d2c54e68304265 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:00:04 -0400 Subject: [PATCH 321/448] deps: bump github.com/go-git/go-git/v5 from 5.17.1 to 5.18.0 in the go_modules group across 1 directory (#2212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the go_modules group with 1 update in the / directory: [github.com/go-git/go-git/v5](https://github.com/go-git/go-git). Updates `github.com/go-git/go-git/v5` from 5.17.1 to 5.18.0
Release notes

Sourced from github.com/go-git/go-git/v5's releases.

v5.18.0

What's Changed

Full Changelog: https://github.com/go-git/go-git/compare/v5.17.2...v5.18.0

v5.17.2

What's Changed

:warning: This release fixes a bug (go-git/go-git#1942) that blocked some users from upgrading to v5.17.1. Thanks @​pskrbasu for reporting it. :bow:

Full Changelog: https://github.com/go-git/go-git/compare/v5.17.1...v5.17.2

Commits
  • ea3e7ec Merge pull request #2004 from go-git/v5-http-hardening
  • bcd20a9 plumbing: transport/http, Add support for followRedirects policy
  • 45ae193 Merge pull request #1944 from go-git/fix-perms
  • fda4f74 storage: filesystem/dotgit, Skip writing pack files that already exist on disk
  • 2212dc7 Merge pull request #1941 from go-git/renovate/releases/v5.x-go-github.com-go-...
  • ebb2d7d build: Update module github.com/go-git/go-git/v5 to v5.17.1 [SECURITY]
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-git/go-git/v5&package-manager=go_modules&previous-version=5.17.1&new-version=5.18.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 81 +++++++++++---------- go.sum | 218 +++++++++++++++++++++++++++------------------------------ 2 files changed, 145 insertions(+), 154 deletions(-) diff --git a/go.mod b/go.mod index 286836cbc9..6cf1843ea1 100644 --- a/go.mod +++ b/go.mod @@ -87,16 +87,16 @@ require ( github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.24.1 // indirect - github.com/go-openapi/errors v0.22.6 // indirect - github.com/go-openapi/jsonpointer v0.22.4 // indirect - github.com/go-openapi/jsonreference v0.21.4 // indirect - github.com/go-openapi/loads v0.23.2 // indirect - github.com/go-openapi/runtime v0.29.2 // indirect - github.com/go-openapi/spec v0.22.3 // indirect - github.com/go-openapi/strfmt v0.25.0 // indirect - github.com/go-openapi/swag v0.25.4 // indirect - github.com/go-openapi/validate v0.25.1 // indirect + github.com/go-openapi/analysis v0.24.3 // indirect + github.com/go-openapi/errors v0.22.7 // indirect + github.com/go-openapi/jsonpointer v0.22.5 // indirect + github.com/go-openapi/jsonreference v0.21.5 // indirect + github.com/go-openapi/loads v0.23.3 // indirect + github.com/go-openapi/runtime v0.29.3 // indirect + github.com/go-openapi/spec v0.22.4 // indirect + github.com/go-openapi/strfmt v0.26.0 // indirect + github.com/go-openapi/swag v0.25.5 // indirect + github.com/go-openapi/validate v0.25.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect @@ -137,7 +137,6 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect @@ -165,7 +164,6 @@ require ( go.etcd.io/etcd/api/v3 v3.6.7 // indirect go.etcd.io/etcd/client/pkg/v3 v3.6.7 // indirect go.etcd.io/etcd/client/v3 v3.6.7 // indirect - go.mongodb.org/mongo-driver v1.17.6 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.uber.org/dig v1.17.1 // indirect @@ -287,15 +285,15 @@ require ( require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect - cloud.google.com/go v0.121.6 // indirect - cloud.google.com/go/auth v0.18.0 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.18.2 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.3 // indirect - cloud.google.com/go/kms v1.23.2 // indirect - cloud.google.com/go/longrunning v0.7.0 // indirect + cloud.google.com/go/kms v1.25.0 // indirect + cloud.google.com/go/longrunning v0.8.0 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect - cloud.google.com/go/storage v1.57.1 // indirect + cloud.google.com/go/storage v1.57.2 // indirect code.gitea.io/sdk/gitea v0.18.0 // indirect codeberg.org/chavacava/garif v0.2.0 // indirect codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect @@ -319,7 +317,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v2 v2.0.0 // indirect github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect - github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect + github.com/Azure/go-autorest/autorest/to v0.4.1 // indirect github.com/Azure/msi-dataplane v0.4.3 // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect @@ -347,7 +345,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.49.1 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.49.5 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect @@ -435,18 +433,18 @@ require ( github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.8.0 // indirect - github.com/go-git/go-git/v5 v5.17.1 // indirect - github.com/go-openapi/swag/cmdutils v0.25.4 // indirect - github.com/go-openapi/swag/conv v0.25.4 // indirect - github.com/go-openapi/swag/fileutils v0.25.4 // indirect - github.com/go-openapi/swag/jsonname v0.25.4 // indirect - github.com/go-openapi/swag/jsonutils v0.25.4 // indirect - github.com/go-openapi/swag/loading v0.25.4 // indirect - github.com/go-openapi/swag/mangling v0.25.4 // indirect - github.com/go-openapi/swag/netutils v0.25.4 // indirect - github.com/go-openapi/swag/stringutils v0.25.4 // indirect - github.com/go-openapi/swag/typeutils v0.25.4 // indirect - github.com/go-openapi/swag/yamlutils v0.25.4 // indirect + github.com/go-git/go-git/v5 v5.18.0 // indirect + github.com/go-openapi/swag/cmdutils v0.25.5 // indirect + github.com/go-openapi/swag/conv v0.25.5 // indirect + github.com/go-openapi/swag/fileutils v0.25.5 // indirect + github.com/go-openapi/swag/jsonname v0.25.5 // indirect + github.com/go-openapi/swag/jsonutils v0.25.5 // indirect + github.com/go-openapi/swag/loading v0.25.5 // indirect + github.com/go-openapi/swag/mangling v0.25.5 // indirect + github.com/go-openapi/swag/netutils v0.25.5 // indirect + github.com/go-openapi/swag/stringutils v0.25.5 // indirect + github.com/go-openapi/swag/typeutils v0.25.5 // indirect + github.com/go-openapi/swag/yamlutils v0.25.5 // indirect github.com/go-restruct/restruct v1.2.0-alpha // indirect github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect @@ -481,9 +479,9 @@ require ( github.com/google/rpmpack v0.7.1 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect - github.com/google/wire v0.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.9 // indirect - github.com/googleapis/gax-go/v2 v2.16.0 // indirect + github.com/google/wire v0.7.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.12 // indirect + github.com/googleapis/gax-go/v2 v2.17.0 // indirect github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/goreleaser/chglog v0.6.1 // indirect github.com/goreleaser/fileglob v1.3.0 // indirect @@ -574,6 +572,7 @@ require ( github.com/nishanths/predeclared v0.2.2 // indirect github.com/nunnatsa/ginkgolinter v0.23.0 // indirect github.com/nxadm/tail v1.4.11 // indirect + github.com/oklog/ulid/v2 v2.1.1 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml v1.9.5 // indirect @@ -601,11 +600,11 @@ require ( github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/shibumi/go-pathspec v1.3.0 // indirect - github.com/sigstore/cosign/v2 v2.6.2 // indirect + github.com/sigstore/cosign/v2 v2.6.3 // indirect github.com/sigstore/protobuf-specs v0.5.0 // indirect - github.com/sigstore/rekor v1.5.0 // indirect + github.com/sigstore/rekor v1.5.1 // indirect github.com/sigstore/rekor-tiles/v2 v2.0.1 // indirect - github.com/sigstore/sigstore v1.10.4 // indirect + github.com/sigstore/sigstore v1.10.5 // indirect github.com/sigstore/sigstore-go v1.1.4 // indirect github.com/sigstore/timestamp-authority/v2 v2.0.3 // indirect github.com/sirupsen/logrus v1.9.4 // indirect @@ -669,11 +668,11 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - gocloud.dev v0.40.0 // indirect + gocloud.dev v0.45.0 // indirect golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect - golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect - google.golang.org/api v0.260.0 // indirect - google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect + google.golang.org/api v0.269.0 // indirect + google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/mail.v2 v2.3.1 // indirect diff --git a/go.sum b/go.sum index 949668bc57..d12f8199c4 100644 --- a/go.sum +++ b/go.sum @@ -5,26 +5,26 @@ cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c= -cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI= -cloud.google.com/go/auth v0.18.0 h1:wnqy5hrv7p3k7cShwAU/Br3nzod7fxoqG+k0VZ+/Pk0= -cloud.google.com/go/auth v0.18.0/go.mod h1:wwkPM1AgE1f2u6dG443MiWoD8C3BtOywNsUMcUTVDRo= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= +cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= -cloud.google.com/go/kms v1.23.2 h1:4IYDQL5hG4L+HzJBhzejUySoUOheh3Lk5YT4PCyyW6k= -cloud.google.com/go/kms v1.23.2/go.mod h1:rZ5kK0I7Kn9W4erhYVoIRPtpizjunlrfU4fUkumUp8g= +cloud.google.com/go/kms v1.25.0 h1:gVqvGGUmz0nYCmtoxWmdc1wli2L1apgP8U4fghPGSbQ= +cloud.google.com/go/kms v1.25.0/go.mod h1:XIdHkzfj0bUO3E+LvwPg+oc7s58/Ns8Nd8Sdtljihbk= cloud.google.com/go/logging v1.13.1 h1:O7LvmO0kGLaHY/gq8cV7T0dyp6zJhYAOtZPX4TF3QtY= cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= -cloud.google.com/go/longrunning v0.7.0 h1:FV0+SYF1RIj59gyoWDRi45GiYUMM3K1qO51qoboQT1E= -cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY= +cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7EhfW8= +cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= -cloud.google.com/go/storage v1.57.1 h1:gzao6odNJ7dR3XXYvAgPK+Iw4fVPPznEPPyNjbaVkq8= -cloud.google.com/go/storage v1.57.1/go.mod h1:329cwlpzALLgJuu8beyJ/uvQznDHpa2U5lGjWednkzg= +cloud.google.com/go/storage v1.57.2 h1:sVlym3cHGYhrp6XZKkKb+92I1V42ks2qKKpB0CF5Mb4= +cloud.google.com/go/storage v1.57.2/go.mod h1:n5ijg4yiRXXpCu0sJTD6k+eMf7GRrJmPyr9YxLXGHOk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= @@ -42,8 +42,9 @@ dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKf dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= -filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= +filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ= @@ -151,8 +152,8 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/to v0.4.1 h1:CxNHBqdzTr7rLtdrtb5CMjJcDut+WNGCVv7OmS5+lTc= +github.com/Azure/go-autorest/autorest/to v0.4.1/go.mod h1:EtaofgU4zmtvn1zT2ARsjRFdq9vXx0YWtmElwL+GZ9M= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= @@ -288,8 +289,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3x github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= -github.com/aws/aws-sdk-go-v2/service/kms v1.49.1 h1:U0asSZ3ifpuIehDPkRI2rxHbmFUMplDA2VeR9Uogrmw= -github.com/aws/aws-sdk-go-v2/service/kms v1.49.1/go.mod h1:NZo9WJqQ0sxQ1Yqu1IwCHQFQunTms2MlVgejg16S1rY= +github.com/aws/aws-sdk-go-v2/service/kms v1.49.5 h1:DKibav4XF66XSeaXcrn9GlWGHos6D/vJ4r7jsK7z5CE= +github.com/aws/aws-sdk-go-v2/service/kms v1.49.5/go.mod h1:1SdcmEGUEQE1mrU2sIgeHtcMSxHuybhPvuEPANzIDfI= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= @@ -627,8 +628,8 @@ github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDz github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.17.1 h1:WnljyxIzSj9BRRUlnmAU35ohDsjRK0EKmL0evDqi5Jk= -github.com/go-git/go-git/v5 v5.17.1/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= +github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= @@ -640,54 +641,54 @@ 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-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/analysis v0.24.1 h1:Xp+7Yn/KOnVWYG8d+hPksOYnCYImE3TieBa7rBOesYM= -github.com/go-openapi/analysis v0.24.1/go.mod h1:dU+qxX7QGU1rl7IYhBC8bIfmWQdX4Buoea4TGtxXY84= -github.com/go-openapi/errors v0.22.6 h1:eDxcf89O8odEnohIXwEjY1IB4ph5vmbUsBMsFNwXWPo= -github.com/go-openapi/errors v0.22.6/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= -github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4= -github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80= -github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8= -github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4= -github.com/go-openapi/loads v0.23.2 h1:rJXAcP7g1+lWyBHC7iTY+WAF0rprtM+pm8Jxv1uQJp4= -github.com/go-openapi/loads v0.23.2/go.mod h1:IEVw1GfRt/P2Pplkelxzj9BYFajiWOtY2nHZNj4UnWY= -github.com/go-openapi/runtime v0.29.2 h1:UmwSGWNmWQqKm1c2MGgXVpC2FTGwPDQeUsBMufc5Yj0= -github.com/go-openapi/runtime v0.29.2/go.mod h1:biq5kJXRJKBJxTDJXAa00DOTa/anflQPhT0/wmjuy+0= -github.com/go-openapi/spec v0.22.3 h1:qRSmj6Smz2rEBxMnLRBMeBWxbbOvuOoElvSvObIgwQc= -github.com/go-openapi/spec v0.22.3/go.mod h1:iIImLODL2loCh3Vnox8TY2YWYJZjMAKYyLH2Mu8lOZs= -github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= -github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= -github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= -github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= -github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= -github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= -github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= -github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= -github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= -github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= -github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= -github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= -github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM= -github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= -github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= -github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= -github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= -github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= -github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= -github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= -github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= -github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= -github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= -github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= -github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= -github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= -github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= -github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= -github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= -github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw= -github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc= +github.com/go-openapi/analysis v0.24.3 h1:a1hrvMr8X0Xt69KP5uVTu5jH62DscmDifrLzNglAayk= +github.com/go-openapi/analysis v0.24.3/go.mod h1:Nc+dWJ/FxZbhSow5Yh3ozg5CLJioB+XXT6MdLvJUsUw= +github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA= +github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w= +github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA= +github.com/go-openapi/jsonpointer v0.22.5/go.mod h1:gyUR3sCvGSWchA2sUBJGluYMbe1zazrYWIkWPjjMUY0= +github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= +github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= +github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ= +github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA= +github.com/go-openapi/runtime v0.29.3 h1:h5twGaEqxtQg40ePiYm9vFFH1q06Czd7Ot6ufdK0w/Y= +github.com/go-openapi/runtime v0.29.3/go.mod h1:8A1W0/L5eyNJvKciqZtvIVQvYO66NlB7INMSZ9bw/oI= +github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ= +github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ= +github.com/go-openapi/strfmt v0.26.0 h1:SDdQLyOEqu8W96rO1FRG1fuCtVyzmukky0zcD6gMGLU= +github.com/go-openapi/strfmt v0.26.0/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y= +github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU= +github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA= +github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c= +github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g= +github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k= +github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk= +github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc= +github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo= +github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU= +github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo= +github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5 h1:SX6sE4FrGb4sEnnxbFL/25yZBb5Hcg1inLeErd86Y1U= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5/go.mod h1:/2KvOTrKWjVA5Xli3DZWdMCZDzz3uV/T7bXwrKWPquo= +github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU= +github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g= +github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw= +github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY= +github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU= +github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14= +github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M= +github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII= +github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E= +github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc= +github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ= +github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.1 h1:NZOrZmIb6PTv5LTFxr5/mKV/FjbUzGE7E6gLz7vFoOQ= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.1/go.mod h1:r7dwsujEHawapMsxA69i+XMGZrQ5tRauhLAjV/sxg3Q= +github.com/go-openapi/testify/v2 v2.4.1 h1:zB34HDKj4tHwyUQHrUkpV0Q0iXQ6dUCOQtIqn8hE6Iw= +github.com/go-openapi/testify/v2 v2.4.1/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0= +github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY= github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s= github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI= github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc= @@ -850,18 +851,17 @@ github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+ github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg= 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/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/trillian v1.7.2 h1:EPBxc4YWY4Ak8tcuhyFleY+zYlbCDCa4Sn24e1Ka8Js= github.com/google/trillian v1.7.2/go.mod h1:mfQJW4qRH6/ilABtPYNBerVJAJ/upxHLX81zxNQw05s= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= -github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= -github.com/googleapis/enterprise-certificate-proxy v0.3.9 h1:TOpi/QG8iDcZlkQlGlFUti/ZtyLkliXvHDcyUIMuFrU= -github.com/googleapis/enterprise-certificate-proxy v0.3.9/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= -github.com/googleapis/gax-go/v2 v2.16.0 h1:iHbQmKLLZrexmb0OSsNGTeSTS0HO4YvFOG8g5E4Zd0Y= -github.com/googleapis/gax-go/v2 v2.16.0/go.mod h1:o1vfQjjNZn4+dPnRdl/4ZD7S9414Y4xA+a/6Icj6l14= +github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4= +github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18= +github.com/googleapis/enterprise-certificate-proxy v0.3.12 h1:Fg+zsqzYEs1ZnvmcztTYxhgCBsx3eEhEwQ1W/lHq/sQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.12/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= github.com/gopacket/gopacket v1.5.0 h1:9s9fcSUVKFlRV97B77Bq9XNV3ly2gvvsneFMQUGjc+M= github.com/gopacket/gopacket v1.5.0/go.mod h1:i3NaGaqfoWKAr1+g7qxEdWsmfT+MXuWkAe9+THv8LME= @@ -1096,8 +1096,8 @@ github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/letsencrypt/boulder v0.20251110.0 h1:J8MnKICeilO91dyQ2n5eBbab24neHzUpYMUIOdOtbjc= -github.com/letsencrypt/boulder v0.20251110.0/go.mod h1:ogKCJQwll82m7OVHWyTuf8eeFCjuzdRQlgnZcCl0V+8= +github.com/letsencrypt/boulder v0.20260223.0 h1:xdS2OnJNUasR6TgVIOpqqcvdkOu47+PQQMBk9ThuWBw= +github.com/letsencrypt/boulder v0.20260223.0/go.mod h1:r3aTSA7UZ7dbDfiGK+HLHJz0bWNbHk6YSPiXgzl23sA= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= @@ -1257,8 +1257,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= +github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -1289,6 +1289,7 @@ github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pborman/getopt v0.0.0-20180811024354-2b5b3bfb099b/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -1345,8 +1346,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1 h1:+o7rrBoj54t8fqQSmnwRLdLzp5 github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1/go.mod h1:bWIjbxmrAk9eKGg9LSko3oQefoYGyWV4xzNS55PgL60= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1 h1:LJF39lvUagUpKfL2/gZIp5vHv3AwXt9zOZ/Xual/CzI= github.com/redis/go-redis/extra/redisotel/v9 v9.7.1/go.mod h1:VAY1vDpD/dLwfw/wU5SsexXNhCO9DjhRoGkmJeFONoE= -github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI= -github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370= +github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs= +github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1400,26 +1401,26 @@ github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+D github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sigstore/cosign/v2 v2.6.2 h1:mi6EAUJoPZ+yuyooU7m06a1DZWJouwYgh9a67L9tm2M= -github.com/sigstore/cosign/v2 v2.6.2/go.mod h1:g+P/LgYyJkC85WGGDho7yySl3C6xTJzzpLm21ZV+E6s= +github.com/sigstore/cosign/v2 v2.6.3 h1:1W+rZWz0zkTfqmTmYBOQS/Jt97NKz1OCzxTV2YAp1+s= +github.com/sigstore/cosign/v2 v2.6.3/go.mod h1:g+P/LgYyJkC85WGGDho7yySl3C6xTJzzpLm21ZV+E6s= github.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY= github.com/sigstore/protobuf-specs v0.5.0/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc= -github.com/sigstore/rekor v1.5.0 h1:rL7SghHd5HLCtsCrxw0yQg+NczGvM75EjSPPWuGjaiQ= -github.com/sigstore/rekor v1.5.0/go.mod h1:D7JoVCUkxwQOpPDNYeu+CE8zeBC18Y5uDo6tF8s2rcQ= +github.com/sigstore/rekor v1.5.1 h1:Ca1egHRWRuDvXV4tZu9aXEXc3Gej9FG+HKeapV9OAMQ= +github.com/sigstore/rekor v1.5.1/go.mod h1:gTLDuZuo3SyQCuZvKqwRPA79Qo/2rw39/WtLP/rZjUQ= github.com/sigstore/rekor-tiles/v2 v2.0.1 h1:1Wfz15oSRNGF5Dzb0lWn5W8+lfO50ork4PGIfEKjZeo= github.com/sigstore/rekor-tiles/v2 v2.0.1/go.mod h1:Pjsbhzj5hc3MKY8FfVTYHBUHQEnP0ozC4huatu4x7OU= -github.com/sigstore/sigstore v1.10.4 h1:ytOmxMgLdcUed3w1SbbZOgcxqwMG61lh1TmZLN+WeZE= -github.com/sigstore/sigstore v1.10.4/go.mod h1:tDiyrdOref3q6qJxm2G+JHghqfmvifB7hw+EReAfnbI= +github.com/sigstore/sigstore v1.10.5 h1:KqrOjDhNOVY+uOzQFat2FrGLClPPCb3uz8pK3wuI+ow= +github.com/sigstore/sigstore v1.10.5/go.mod h1:k/mcVVXw3I87dYG/iCVTSW2xTrW7vPzxxGic4KqsqXs= github.com/sigstore/sigstore-go v1.1.4 h1:wTTsgCHOfqiEzVyBYA6mDczGtBkN7cM8mPpjJj5QvMg= github.com/sigstore/sigstore-go v1.1.4/go.mod h1:2U/mQOT9cjjxrtIUeKDVhL+sHBKsnWddn8URlswdBsg= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.3 h1:D/FRl5J9UYAJPGZRAJbP0dH78pfwWnKsyCSBwFBU8CI= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.3/go.mod h1:2GIWuNvTRMvrzd0Nl8RNqxrt9H7X0OBStwOSzGYRjYw= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.3 h1:k5VMLf/ms7hh6MLgVoorM0K+hSMwZLXoywlxh4CXqP8= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.3/go.mod h1:S1Bp3dmP7jYlXcGLAxG81wRbE01NIZING8ZIy0dJlAI= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.3 h1:AVWs0E6rVZMoDTE0Iyezrpo1J6RlI5B4QZhAC4FLE30= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.3/go.mod h1:nxQYF0D6u7mVtiP1azj1YVDIrtz7S0RYCVTqUG8IcCk= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.3 h1:lJSdaC/aOlFHlvqmmV696n1HdXLMLEKGwpNZMV0sKts= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.3/go.mod h1:b2rV9qPbt/jv/Yy75AIOZThP8j+pe1ZdLEjOwmjPdoA= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.4 h1:VZ+L6SKVWbLPHznIF0tBuO7qKMFdJiJMVwFKu9DlY5o= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.4/go.mod h1:Rstj47WpJym25il8j4jTL0BfikzP/9AhVD+DsBcYzZc= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.4 h1:G7yOv8bxk3zIEEZyVCixPxtePIAm+t3ZWSaKRPzVw+o= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.4/go.mod h1:hxJelB/bRItMYOzi6qD9xEKjse2QZcikh4TbysfdDHc= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.4 h1:Qxt6dE4IwhJ6gIXmg2q4S/SeqEDSZ29nmfsv7Zb6LL4= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.4/go.mod h1:hJVeNOwarqfyALjOwsf0OR8YA/A96NABucEaQumPr30= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.4 h1:KVavYMPfSf5NryOl6VrZ9nRG3fXOOJOPp7Czk/YCPkM= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.4/go.mod h1:J7CA1AaBkyK8dYq6EdQANhj+8oEcsA7PrIp088qgPiY= github.com/sigstore/timestamp-authority/v2 v2.0.3 h1:sRyYNtdED/ttLCMdaYnwpf0zre1A9chvjTnCmWWxN8Y= github.com/sigstore/timestamp-authority/v2 v2.0.3/go.mod h1:mDaHxkt3HmZYoIlwYj4QWo0RUr7VjYU52aVO5f5Qb3I= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -1623,8 +1624,6 @@ go.etcd.io/etcd/client/pkg/v3 v3.6.7 h1:vvzgyozz46q+TyeGBuFzVuI53/yd133CHceNb/Ah go.etcd.io/etcd/client/pkg/v3 v3.6.7/go.mod h1:2IVulJ3FZ/czIGl9T4lMF1uxzrhRahLqe+hSgy+Kh7Q= go.etcd.io/etcd/client/v3 v3.6.7 h1:9WqA5RpIBtdMxAy1ukXLAdtg2pAxNqW5NUoO2wQrE6U= go.etcd.io/etcd/client/v3 v3.6.7/go.mod h1:2XfROY56AXnUqGsvl+6k29wrwsSbEh1lAouQB1vHpeE= -go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= -go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= @@ -1659,8 +1658,8 @@ go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18 go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0 h1:k6KdfZk72tVW/QVZf60xlDziDvYAePj5QHwoQvrB2m8= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0/go.mod h1:5Y3ZJLqzi/x/kYtrSrPSx7TFI/SGsL7q2kME027tH6I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1xzhKrotaHy3/KXdPhlWARrCgK+eqUY= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0 h1:6VjV6Et+1Hd2iLZEPtdV7vie80Yyqf7oikJLjQ/myi0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0/go.mod h1:u8hcp8ji5gaM/RfcOo8z9NMnf1pVLfVY7lBY2VOGuUU= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4= @@ -1677,8 +1676,8 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09 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= -go.step.sm/crypto v0.75.0 h1:UAHYD6q6ggYyzLlIKHv1MCUVjZIesXRZpGTlRC/HSHw= -go.step.sm/crypto v0.75.0/go.mod h1:wwQ57+ajmDype9mrI/2hRyrvJd7yja5xVgWYqpUN3PE= +go.step.sm/crypto v0.76.2 h1:JJ/yMcs/rmcCAwlo+afrHjq74XBFRTJw5B2y4Q4Z4c4= +go.step.sm/crypto v0.76.2/go.mod h1:m6KlB/HzIuGFep0UWI5e0SYi38UxpoKeCg6qUaHV6/Q= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -1709,8 +1708,8 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -gocloud.dev v0.40.0 h1:f8LgP+4WDqOG/RXoUcyLpeIAGOcAbZrZbDQCUee10ng= -gocloud.dev v0.40.0/go.mod h1:drz+VyYNBvrMTW0KZiBAYEdl8lbNZx+OQ7oQvdrFmSQ= +gocloud.dev v0.45.0 h1:WknIK8IbRdmynDvara3Q7G6wQhmEiOGwpgJufbM39sY= +gocloud.dev v0.45.0/go.mod h1:0kXKmkCLG6d31N7NyLZWzt7jDSQura9zD/mWgiB6THI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1725,7 +1724,6 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1751,7 +1749,6 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1785,7 +1782,6 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1803,7 +1799,6 @@ golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1859,7 +1854,6 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1869,7 +1863,6 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1910,7 +1903,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= @@ -1921,21 +1913,21 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk= -golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.260.0 h1:XbNi5E6bOVEj/uLXQRlt6TKuEzMD7zvW/6tNwltE4P4= -google.golang.org/api v0.260.0/go.mod h1:Shj1j0Phr/9sloYrKomICzdYgsSDImpTxME8rGLaZ/o= +google.golang.org/api v0.269.0 h1:qDrTOxKUQ/P0MveH6a7vZ+DNHxJQjtGm/uvdbdGXCQg= +google.golang.org/api v0.269.0/go.mod h1:N8Wpcu23Tlccl0zSHEkcAZQKDLdquxK+l9r2LkwAauE= 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-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 h1:GvESR9BIyHUahIb0NcTum6itIWtdoglGX+rnGxm2934= -google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:yJ2HH4EHEDTd3JiLmhds6NkJ17ITVYOdV3m3VKOnws0= +google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= +google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= 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-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= From 95f7abfc25d1b1a061b76e1e214e51873e1e1320 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 20:56:19 +0000 Subject: [PATCH 322/448] deps: bump the go_modules group across 1 directory with 4 updates (#2213) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the go_modules group with 4 updates in the / directory: [github.com/moby/spdystream](https://github.com/moby/spdystream), [github.com/buger/jsonparser](https://github.com/buger/jsonparser), [github.com/sigstore/timestamp-authority/v2](https://github.com/sigstore/timestamp-authority) and [github.com/theupdateframework/go-tuf/v2](https://github.com/theupdateframework/go-tuf). Updates `github.com/moby/spdystream` from 0.5.0 to 0.5.1
Release notes

Sourced from github.com/moby/spdystream's releases.

v0.5.1

What's Changed

Security

Fix memory amplification in SPDY frame parsing leads to denial of service (CVE-2026-35469 / GHSA-pc3f-x583-g7j2)

Changes

Full Changelog: https://github.com/moby/spdystream/compare/v0.5.0...v0.5.1

Commits
  • c59e5d7 Merge pull request #109 from thaJeztah/use_ioutil
  • 2fd0155 use ioutil.Discard for go1.13 compatibility
  • ef6121f Merge commit from fork
  • 241cec9 compare with signed Int for 32-bit Arm
  • 21c3864 Add options to customize limits
  • acf9b45 spdy: update godoc for MaxDataLength
  • eb63605 spdy: limit header-size and header-count
  • 2f21da4 spdy: fix header block byte accounting
  • 5976b66 spdy: enforce 24-bit frame length limits
  • cf0ec5d Guard against oversized SPDY frames
  • Additional commits viewable in compare view

Updates `github.com/buger/jsonparser` from 1.1.1 to 1.1.2
Release notes

Sourced from github.com/buger/jsonparser's releases.

v1.1.2

What's Changed

New Contributors

Full Changelog: https://github.com/buger/jsonparser/compare/v1.1.1...v1.1.2

Commits
  • a69e7e0 Merge pull request #276 from dbarrosop/master
  • d3eacc0 fix: prevent panic on negative slice index in Delete with malformed JSON (GO-...
  • 61b32cf Merge pull request #241 from unxcepted/master
  • 2181e83 Merge pull request #244 from ScaleChamp/patch-2
  • 1510b51 Added latest versions of go to tests
  • 6fc2e48 fix: eachkey allocation
  • a6f867e Merge pull request #239 from AdamKorcz/cifuzz1
  • cbc01fd Fuzzing: Add CIFuzz
  • dc92d69 Merge pull request #228 from jonomacd/null-handling
  • 2d9d634 Merge pull request #231 from carsonip/fix-parseint-overflow-check
  • Additional commits viewable in compare view

Updates `github.com/sigstore/timestamp-authority/v2` from 2.0.3 to 2.0.6
Release notes

Sourced from github.com/sigstore/timestamp-authority/v2's releases.

v2.0.6

What's Changed

Full Changelog: https://github.com/sigstore/timestamp-authority/compare/v2.0.5...v2.0.6

v2.0.5

What's Changed

This release updates the chi middleware to resolve a panic.

Full Changelog: https://github.com/sigstore/timestamp-authority/compare/v2.0.4...v2.0.5

v2.0.4

Changelog

  • 5ddd4e6ad32117ae431eca6299ed9d29a6d33f5a update changelog for v2.0.4 (#1258)

What's Changed

Full Changelog: https://github.com/sigstore/timestamp-authority/compare/v2.0.3...v2.0.4

Changelog

Sourced from github.com/sigstore/timestamp-authority/v2's changelog.

v2.0.5

This release updates the chi middleware to resolve a panic.

Bug Fixes

  • Upgrade chi middleware v4 -> v5 (#1307)

Docs

  • Update the semantics of the NTP monitoring so its clear in the README (#1276)
  • docs: note that CRL/OCSP checks are not performed (#1277)

Misc

  • Increase default HTTP idle timeout (#1287)

v2.0.4

Only contains dependency updates, but fixes #1252 due to breaking API change in sigstore/sigstore

Commits
  • 9583b61 Ensure correct certificate is used for TSA auth checks (GHSA-xm5m-wgh2-rrg3) ...
  • 7aab8b4 chore(deps): bump golang.org/x/net from 0.51.0 to 0.52.0 (#1322)
  • 48c7b2c chore(deps): bump codecov/codecov-action from 5.5.3 to 6.0.0 (#1327)
  • 49ca4e4 chore(deps): bump the gomod group with 2 updates (#1326)
  • 5812ba0 chore(deps): bump go.step.sm/crypto from 0.76.2 to 0.77.2 (#1328)
  • 6a334a8 chore(deps): bump github.com/go-jose/go-jose/v4 from 4.1.3 to 4.1.4 (#1329)
  • d799204 chore(deps): bump actions/upload-artifact in the actions group (#1332)
  • b9ce102 chore(deps): bump golang from 1.26.0 to 1.26.2 in the docker group (#1331)
  • 54bc0c1 chore(deps): bump the gomod group across 1 directory with 6 updates (#1324)
  • ffb897a chore(deps): bump the actions group across 1 directory with 4 updates (#1325)
  • Additional commits viewable in compare view

Updates `github.com/theupdateframework/go-tuf/v2` from 2.3.0 to 2.4.1
Release notes

Sourced from github.com/theupdateframework/go-tuf/v2's releases.

v2.4.1

What's Changed

Full Changelog: https://github.com/theupdateframework/go-tuf/compare/v2.4.0...v2.4.1

v2.4.0

What's Changed

Full Changelog: https://github.com/theupdateframework/go-tuf/compare/v2.3.1...v2.4.0

v2.3.1

What's Changed

Full Changelog: https://github.com/theupdateframework/go-tuf/compare/v2.3.0...v2.3.1

Commits
  • d361e2e Enforce a stricter validation on the repo name for TAP 4 (#720)
  • 29aae36 chore(deps): bump github.com/sigstore/sigstore from 1.10.3 to 1.10.4 (#718)
  • bde5f18 Replace panic with error return in Key.ID() (#713)
  • f400bf4 Use restrictive permissions (0700) for cache directories (#714)
  • d2dbc18 Add thread safety documentation for key types (#715)
  • 846cd4e Add BitLength validation for SuccinctRoles (#716)
  • b38d91f Verify threshold is valid (#712)
  • 876cf2a Add tests for failing type assertions (#711)
  • 73345ab Perform type assertion (#710)
  • d3cdc4b chore(deps): bump github.com/secure-systems-lab/go-securesystemslib from 0.9....
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 26 +++++++++---------- go.sum | 80 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/go.mod b/go.mod index 6cf1843ea1..c67af8284a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/microsoft/retina -go 1.25.0 +go 1.25.5 require ( github.com/go-chi/chi/v5 v5.2.5 @@ -94,7 +94,7 @@ require ( github.com/go-openapi/loads v0.23.3 // indirect github.com/go-openapi/runtime v0.29.3 // indirect github.com/go-openapi/spec v0.22.4 // indirect - github.com/go-openapi/strfmt v0.26.0 // indirect + github.com/go-openapi/strfmt v0.26.1 // indirect github.com/go-openapi/swag v0.25.5 // indirect github.com/go-openapi/validate v0.25.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect @@ -132,7 +132,7 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/spdystream v0.5.0 // indirect + github.com/moby/spdystream v0.5.1 // indirect github.com/moby/term v0.5.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -196,7 +196,7 @@ require ( github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.53.0 // indirect - golang.org/x/oauth2 v0.35.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.20.0 golang.org/x/sys v0.43.0 golang.org/x/term v0.42.0 // indirect @@ -290,7 +290,7 @@ require ( cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.3 // indirect - cloud.google.com/go/kms v1.25.0 // indirect + cloud.google.com/go/kms v1.26.0 // indirect cloud.google.com/go/longrunning v0.8.0 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.57.2 // indirect @@ -345,7 +345,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.49.5 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect @@ -361,7 +361,7 @@ require ( github.com/bombsimon/wsl/v5 v5.6.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect - github.com/buger/jsonparser v1.1.1 // indirect + github.com/buger/jsonparser v1.1.2 // indirect github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/caarlos0/ctrlc v1.2.0 // indirect @@ -480,8 +480,8 @@ require ( github.com/google/s2a-go v0.1.9 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect github.com/google/wire v0.7.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.12 // indirect - github.com/googleapis/gax-go/v2 v2.17.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/gax-go/v2 v2.19.0 // indirect github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/goreleaser/chglog v0.6.1 // indirect github.com/goreleaser/fileglob v1.3.0 // indirect @@ -606,7 +606,7 @@ require ( github.com/sigstore/rekor-tiles/v2 v2.0.1 // indirect github.com/sigstore/sigstore v1.10.5 // indirect github.com/sigstore/sigstore-go v1.1.4 // indirect - github.com/sigstore/timestamp-authority/v2 v2.0.3 // indirect + github.com/sigstore/timestamp-authority/v2 v2.0.6 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect @@ -619,7 +619,7 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/tetafro/godot v1.5.4 // indirect github.com/theupdateframework/go-tuf v0.7.0 // indirect - github.com/theupdateframework/go-tuf/v2 v2.3.0 // indirect + github.com/theupdateframework/go-tuf/v2 v2.4.1 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect github.com/timonwong/loggercheck v0.11.0 // indirect github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect @@ -671,8 +671,8 @@ require ( gocloud.dev v0.45.0 // indirect golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect - google.golang.org/api v0.269.0 // indirect - google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/api v0.272.0 // indirect + google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/mail.v2 v2.3.1 // indirect diff --git a/go.sum b/go.sum index d12f8199c4..3d50c12dbd 100644 --- a/go.sum +++ b/go.sum @@ -15,10 +15,10 @@ cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdB cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= -cloud.google.com/go/kms v1.25.0 h1:gVqvGGUmz0nYCmtoxWmdc1wli2L1apgP8U4fghPGSbQ= -cloud.google.com/go/kms v1.25.0/go.mod h1:XIdHkzfj0bUO3E+LvwPg+oc7s58/Ns8Nd8Sdtljihbk= -cloud.google.com/go/logging v1.13.1 h1:O7LvmO0kGLaHY/gq8cV7T0dyp6zJhYAOtZPX4TF3QtY= -cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= +cloud.google.com/go/kms v1.26.0 h1:cK9mN2cf+9V63D3H1f6koxTatWy39aTI/hCjz1I+adU= +cloud.google.com/go/kms v1.26.0/go.mod h1:pHKOdFJm63hxBsiPkYtowZPltu9dW0MWvBa6IA4HM58= +cloud.google.com/go/logging v1.13.2 h1:qqlHCBvieJT9Cdq4QqYx1KPadCQ2noD4FK02eNqHAjA= +cloud.google.com/go/logging v1.13.2/go.mod h1:zaybliM3yun1J8mU2dVQ1/qDzjbOqEijZCn6hSBtKak= cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7EhfW8= cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= @@ -43,8 +43,8 @@ dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88 dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= -filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ= @@ -289,8 +289,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3x github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= -github.com/aws/aws-sdk-go-v2/service/kms v1.49.5 h1:DKibav4XF66XSeaXcrn9GlWGHos6D/vJ4r7jsK7z5CE= -github.com/aws/aws-sdk-go-v2/service/kms v1.49.5/go.mod h1:1SdcmEGUEQE1mrU2sIgeHtcMSxHuybhPvuEPANzIDfI= +github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= +github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= @@ -338,8 +338,8 @@ github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDw github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk= +github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E= github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= @@ -655,8 +655,8 @@ github.com/go-openapi/runtime v0.29.3 h1:h5twGaEqxtQg40ePiYm9vFFH1q06Czd7Ot6ufdK github.com/go-openapi/runtime v0.29.3/go.mod h1:8A1W0/L5eyNJvKciqZtvIVQvYO66NlB7INMSZ9bw/oI= github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ= github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ= -github.com/go-openapi/strfmt v0.26.0 h1:SDdQLyOEqu8W96rO1FRG1fuCtVyzmukky0zcD6gMGLU= -github.com/go-openapi/strfmt v0.26.0/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y= +github.com/go-openapi/strfmt v0.26.1 h1:7zGCHji7zSYDC2tCXIusoxYQz/48jAf2q+sF6wXTG+c= +github.com/go-openapi/strfmt v0.26.1/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y= github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU= github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA= github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c= @@ -858,10 +858,10 @@ 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/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4= github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18= -github.com/googleapis/enterprise-certificate-proxy v0.3.12 h1:Fg+zsqzYEs1ZnvmcztTYxhgCBsx3eEhEwQ1W/lHq/sQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.12/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= -github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.19.0 h1:fYQaUOiGwll0cGj7jmHT/0nPlcrZDFPrZRhTsoCr8hE= +github.com/googleapis/gax-go/v2 v2.19.0/go.mod h1:w2ROXVdfGEVFXzmlciUU4EdjHgWvB5h2n6x/8XSTTJA= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= github.com/gopacket/gopacket v1.5.0 h1:9s9fcSUVKFlRV97B77Bq9XNV3ly2gvvsneFMQUGjc+M= github.com/gopacket/gopacket v1.5.0/go.mod h1:i3NaGaqfoWKAr1+g7qxEdWsmfT+MXuWkAe9+THv8LME= @@ -1191,8 +1191,8 @@ github.com/moby/moby/api v1.54.0 h1:7kbUgyiKcoBhm0UrWbdrMs7RX8dnwzURKVbZGy2GnL0= github.com/moby/moby/api v1.54.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc= github.com/moby/moby/client v0.3.0 h1:UUGL5okry+Aomj3WhGt9Aigl3ZOxZGqR7XPo+RLPlKs= github.com/moby/moby/client v0.3.0/go.mod h1:HJgFbJRvogDQjbM8fqc1MCEm4mIAGMLjXbgwoZp6jCQ= -github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= -github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y= +github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= 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= @@ -1413,16 +1413,16 @@ github.com/sigstore/sigstore v1.10.5 h1:KqrOjDhNOVY+uOzQFat2FrGLClPPCb3uz8pK3wuI github.com/sigstore/sigstore v1.10.5/go.mod h1:k/mcVVXw3I87dYG/iCVTSW2xTrW7vPzxxGic4KqsqXs= github.com/sigstore/sigstore-go v1.1.4 h1:wTTsgCHOfqiEzVyBYA6mDczGtBkN7cM8mPpjJj5QvMg= github.com/sigstore/sigstore-go v1.1.4/go.mod h1:2U/mQOT9cjjxrtIUeKDVhL+sHBKsnWddn8URlswdBsg= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.4 h1:VZ+L6SKVWbLPHznIF0tBuO7qKMFdJiJMVwFKu9DlY5o= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.4/go.mod h1:Rstj47WpJym25il8j4jTL0BfikzP/9AhVD+DsBcYzZc= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.4 h1:G7yOv8bxk3zIEEZyVCixPxtePIAm+t3ZWSaKRPzVw+o= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.4/go.mod h1:hxJelB/bRItMYOzi6qD9xEKjse2QZcikh4TbysfdDHc= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.4 h1:Qxt6dE4IwhJ6gIXmg2q4S/SeqEDSZ29nmfsv7Zb6LL4= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.4/go.mod h1:hJVeNOwarqfyALjOwsf0OR8YA/A96NABucEaQumPr30= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.4 h1:KVavYMPfSf5NryOl6VrZ9nRG3fXOOJOPp7Czk/YCPkM= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.4/go.mod h1:J7CA1AaBkyK8dYq6EdQANhj+8oEcsA7PrIp088qgPiY= -github.com/sigstore/timestamp-authority/v2 v2.0.3 h1:sRyYNtdED/ttLCMdaYnwpf0zre1A9chvjTnCmWWxN8Y= -github.com/sigstore/timestamp-authority/v2 v2.0.3/go.mod h1:mDaHxkt3HmZYoIlwYj4QWo0RUr7VjYU52aVO5f5Qb3I= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.5 h1:aqHRubTITULckG9JAcq2FEhtKkT/RRE8oErfuV3smSI= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.5/go.mod h1:h9eK9QyPqpFskF/ewFkRLtwh4/Q3FLc2/DXbym4IHN8= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.5 h1:+9C6CUkv+J4iT67Lx+H1EGBfAdoAHqXumHadeIj9jA4= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.5/go.mod h1:myZsg7wRiy/vf102g5uUAitYhtXCwepmAGxgHG1VHuE= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.5 h1:BpQx6AhjwIN9LmlO4ypkcMcHiWiepgZQGSw5U69frHU= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.5/go.mod h1:ejMD/17lMJ4HykQRPdj5NNr+OQYIEZto8HjDKghVMOA= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.5 h1:OFwQZgWkB/6J6W5sy3SkXE4pJnhNRnE2cJd8ySXmHpo= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.5/go.mod h1:Ee/enmyxi/RFLVlajbnjgH2wOWQwlJ0wY8qZrk43hEw= +github.com/sigstore/timestamp-authority/v2 v2.0.6 h1:1Vh7/SdmLsVLG6Br6/bisd1SnlicfDm0MJYiA+D7Ppw= +github.com/sigstore/timestamp-authority/v2 v2.0.6/go.mod h1:Nk5ucGBDyH0tXAIMZ0prf6xn8qfTnbJhSq+CDabYcfc= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= @@ -1496,8 +1496,8 @@ github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg= github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU= github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug= -github.com/theupdateframework/go-tuf/v2 v2.3.0 h1:gt3X8xT8qu/HT4w+n1jgv+p7koi5ad8XEkLXXZqG9AA= -github.com/theupdateframework/go-tuf/v2 v2.3.0/go.mod h1:xW8yNvgXRncmovMLvBxKwrKpsOwJZu/8x+aB0KtFcdw= +github.com/theupdateframework/go-tuf/v2 v2.4.1 h1:K6ewW064rKZCPkRo1W/CTbTtm/+IB4+coG1iNURAGCw= +github.com/theupdateframework/go-tuf/v2 v2.4.1/go.mod h1:Nex2enPVYDFCklrnbTzl3OVwD7fgIAj0J5++z/rvCj8= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -1516,8 +1516,8 @@ github.com/tink-crypto/tink-go-awskms/v2 v2.1.0 h1:N9UxlsOzu5mttdjhxkDLbzwtEecuX github.com/tink-crypto/tink-go-awskms/v2 v2.1.0/go.mod h1:PxSp9GlOkKL9rlybW804uspnHuO9nbD98V/fDX4uSis= github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0 h1:3B9i6XBXNTRspfkTC0asN5W0K6GhOSgcujNiECNRNb0= github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0/go.mod h1:jY5YN2BqD/KSCHM9SqZPIpJNG/u3zwfLXHgws4x2IRw= -github.com/tink-crypto/tink-go-hcvault/v2 v2.3.0 h1:6nAX1aRGnkg2SEUMwO5toB2tQkP0Jd6cbmZ/K5Le1V0= -github.com/tink-crypto/tink-go-hcvault/v2 v2.3.0/go.mod h1:HOC5NWW1wBI2Vke1FGcRBvDATkEYE7AUDiYbXqi2sBw= +github.com/tink-crypto/tink-go-hcvault/v2 v2.4.0 h1:j+S+WKBQ5ya26A5EM/uXoVe+a2IaPQN8KgBJZ22cJ+4= +github.com/tink-crypto/tink-go-hcvault/v2 v2.4.0/go.mod h1:OCKJIujnTzDq7f+73NhVs99oA2c1TR6nsOpuasYM6Yo= github.com/tink-crypto/tink-go/v2 v2.6.0 h1:+KHNBHhWH33Vn+igZWcsgdEPUxKwBMEe0QC60t388v4= github.com/tink-crypto/tink-go/v2 v2.6.0/go.mod h1:2WbBA6pfNsAfBwDCggboaHeB2X29wkU8XHtGwh2YIk8= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= @@ -1676,8 +1676,8 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09 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= -go.step.sm/crypto v0.76.2 h1:JJ/yMcs/rmcCAwlo+afrHjq74XBFRTJw5B2y4Q4Z4c4= -go.step.sm/crypto v0.76.2/go.mod h1:m6KlB/HzIuGFep0UWI5e0SYi38UxpoKeCg6qUaHV6/Q= +go.step.sm/crypto v0.77.2 h1:qFjjei+RHc5kP5R7NW9OUWT7SqWIuAOvOkXqg4fNWj8= +go.step.sm/crypto v0.77.2/go.mod h1:W0YJb9onM5l78qgkXIJ2Up6grnwW8EtpCKIza/NCg0o= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -1785,8 +1785,8 @@ golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1919,15 +1919,15 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.269.0 h1:qDrTOxKUQ/P0MveH6a7vZ+DNHxJQjtGm/uvdbdGXCQg= -google.golang.org/api v0.269.0/go.mod h1:N8Wpcu23Tlccl0zSHEkcAZQKDLdquxK+l9r2LkwAauE= +google.golang.org/api v0.272.0 h1:eLUQZGnAS3OHn31URRf9sAmRk3w2JjMx37d2k8AjJmA= +google.golang.org/api v0.272.0/go.mod h1:wKjowi5LNJc5qarNvDCvNQBn3rVK8nSy6jg2SwRwzIA= 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-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= -google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= +google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE= +google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw= 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-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= From b0e2475318ffc2bcce95817262ae15e60007eca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 23:53:35 -0400 Subject: [PATCH 323/448] deps: bump actions/setup-node from 6.3.0 to 6.4.0 (#2210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.3.0 to 6.4.0.
Release notes

Sourced from actions/setup-node's releases.

v6.4.0

What's Changed

Dependency updates:

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v6...v6.4.0

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 750ca96c3d..12073387ac 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 20 - name: build From 8d2e5a3a74972c8e8ab9cff703aac22580dc68ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 23:54:36 -0400 Subject: [PATCH 324/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.31.6 to 1.32.14 (#2203) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.31.6 to 1.32.14.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.31.6&new-version=1.32.14)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 29 ++++++++++++++--------------- go.sum | 58 ++++++++++++++++++++++++++++------------------------------ 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index c67af8284a..629a008c71 100644 --- a/go.mod +++ b/go.mod @@ -45,19 +45,18 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect - github.com/aws/smithy-go v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect + github.com/aws/smithy-go v1.25.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -225,9 +224,9 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 github.com/Microsoft/hcsshim v0.14.1 - github.com/aws/aws-sdk-go-v2 v1.41.5 - github.com/aws/aws-sdk-go-v2/config v1.32.14 - github.com/aws/aws-sdk-go-v2/credentials v1.19.14 + github.com/aws/aws-sdk-go-v2 v1.41.6 + github.com/aws/aws-sdk-go-v2/config v1.32.16 + github.com/aws/aws-sdk-go-v2/credentials v1.19.15 github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 @@ -346,7 +345,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 // indirect github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect diff --git a/go.sum b/go.sum index 3d50c12dbd..493eb9a13d 100644 --- a/go.sum +++ b/go.sum @@ -257,52 +257,50 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= -github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= -github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= +github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= -github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= -github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= -github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= -github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM= +github.com/aws/aws-sdk-go-v2/config v1.32.16/go.mod h1:duCCnJEFqpt2RC6no1iK6q+8HpwOAkiUua0pY507dQc= +github.com/aws/aws-sdk-go-v2/credentials v1.19.15 h1:fyvgWTszojq8hEnMi8PPBTvZdTtEVmAVyo+NFLHBhH4= +github.com/aws/aws-sdk-go-v2/credentials v1.19.15/go.mod h1:gJiYyMOjNg8OEdRWOf3CrFQxM2a98qmrtjx1zuiQfB8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 h1:IOGsJ1xVWhsi+ZO7/NW8OuZZBtMJLZbk4P5HDjJO0jQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22/go.mod h1:b+hYdbU+jGKfXE8kKM6g1+h+L/Go3vMvzlxBsiuGsxg= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 h1:1hWFp+52Vq8Fevy/KUhbW/1MEApMz7uitCF/PQXRJpk= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1/go.mod h1:sIec8j802/rCkCKgZV678HFR0s7lhQUYXT77tIvlaa4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U= github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 h1:Bwzh202Aq7/MYnAjXA9VawCf6u+hjwMdoYmZ4HYsdf8= github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1/go.mod h1:xZzWl9AXYa6zsLLH41HBFW8KRKJRIzlGmvSM0mVMIX4= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 h1:XJ/AEFYj9VFPJdF+VFi4SUPEDfz1akHwxxm07JfZJcs= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2/go.mod h1:JUBHdhvKbbKmhaHjLsKJAWnQL80T6nURmhB/LEprV+4= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= -github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= -github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 h1:a1Fq/KXn75wSzoJaPQTgZO0wHGqE9mjFnylnqEPTchA= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.10/go.mod h1:p6+MXNxW7IA6dMgHfTAzljuwSKD0NCm/4lbS4t6+7vI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 h1:x6bKbmDhsgSZwv6q19wY/u3rLk/3FGjJWyqKcIRufpE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.16/go.mod h1:CudnEVKRtLn0+3uMV0yEXZ+YZOKnAtUJ5DmDhilVnIw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 h1:oK/njaL8GtyEihkWMD4k3VgHCT64RQKkZwh0DG5j8ak= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20/go.mod h1:JHs8/y1f3zY7U5WcuzoJ/yAYGYtNIVPKLIbp61euvmg= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 h1:ks8KBcZPh3PYISr5dAiXCM5/Thcuxk8l+PG4+A0exds= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.0/go.mod h1:pFw33T0WLvXU3rw1WBkpMlkgIn54eCB5FYLhjDc9Foo= +github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U= +github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 h1:6lMw4/QGLFPvbKQ0eri/9Oh3YX5Nm6BPrUlZR8yuJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1/go.mod h1:EVJOSYOVeoD3VFFZ/dWCAzWJp5wZr9lTOCjW8ejAmO0= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From 8c84f36babbd29410ece325bf4f2068efdd5534f Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Apr 2026 08:38:28 -0400 Subject: [PATCH 325/448] deps: add per-directory dependabot Docker base image tracking (#1885) # Description Replace the single `directory: "/"` Docker ecosystem entry in dependabot config (which was a no-op since no Dockerfile exists at the repo root) with 7 per-directory entries matching actual Dockerfile locations. Critical components (controller, shell, cli, operator, test/image) are checked daily; tools (kapinger, toolbox) weekly. Also adds a brief section to the development guide documenting the dependabot Docker tracking setup. ## Related Issue Fixes #1884 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Verified all 7 Dockerfile directories exist and match the dependabot entries: `/controller`, `/shell`, `/cli`, `/operator`, `/test/image`, `/hack/tools/kapinger`, `/hack/tools/toolbox` ## Additional Notes Original PR from Copilot SWE agent. Squashed and cleaned up: - Removed `prefix-development` (not applicable to Docker ecosystem) - Replaced non-existent labels (`area/security`, `area/testing`, `area/tools`) with existing `area/infra`, `area/dependencies` - Fixed duplicate broken `## Cleanup` section with unclosed code fence - Removed unnecessary validation script Signed-off-by: Quang Nguyen Co-authored-by: Quang Nguyen Co-authored-by: matmerr <6521405+matmerr@users.noreply.github.com> --- .github/dependabot.yaml | 68 +++++++++++++++++++++++++- docs/08-Contributing/02-development.md | 33 +++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 3e89fa2f7b..b3f317a945 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -1,7 +1,8 @@ version: 2 updates: + # Docker base image tracking - Critical components (daily) - package-ecosystem: "docker" - directory: "/" + directory: "/controller" schedule: interval: "daily" reviewers: @@ -9,7 +10,69 @@ updates: commit-message: prefix: "deps" labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 10 + open-pull-requests-limit: 5 + - package-ecosystem: "docker" + directory: "/shell" + schedule: + interval: "daily" + reviewers: + - "microsoft/retina" + commit-message: + prefix: "deps" + labels: ["area/infra", "area/dependencies"] + open-pull-requests-limit: 5 + - package-ecosystem: "docker" + directory: "/cli" + schedule: + interval: "daily" + reviewers: + - "microsoft/retina" + commit-message: + prefix: "deps" + labels: ["area/infra", "area/dependencies"] + open-pull-requests-limit: 5 + - package-ecosystem: "docker" + directory: "/operator" + schedule: + interval: "daily" + reviewers: + - "microsoft/retina" + commit-message: + prefix: "deps" + labels: ["area/infra", "area/dependencies"] + open-pull-requests-limit: 5 + - package-ecosystem: "docker" + directory: "/test/image" + schedule: + interval: "daily" + reviewers: + - "microsoft/retina" + commit-message: + prefix: "deps" + labels: ["area/infra", "area/dependencies"] + open-pull-requests-limit: 3 + # Docker base image tracking - Tools (weekly) + - package-ecosystem: "docker" + directory: "/hack/tools/kapinger" + schedule: + interval: "weekly" + reviewers: + - "microsoft/retina" + commit-message: + prefix: "deps" + labels: ["area/infra", "area/dependencies"] + open-pull-requests-limit: 3 + - package-ecosystem: "docker" + directory: "/hack/tools/toolbox" + schedule: + interval: "weekly" + reviewers: + - "microsoft/retina" + commit-message: + prefix: "deps" + labels: ["area/infra", "area/dependencies"] + open-pull-requests-limit: 3 + # GitHub Actions tracking - package-ecosystem: "github-actions" directory: "/" schedule: @@ -20,6 +83,7 @@ updates: prefix: "deps" labels: ["area/infra", "area/dependencies"] open-pull-requests-limit: 10 + # Go modules tracking - package-ecosystem: "gomod" directory: "/" schedule: diff --git a/docs/08-Contributing/02-development.md b/docs/08-Contributing/02-development.md index 7f7ba22f29..67353969b5 100644 --- a/docs/08-Contributing/02-development.md +++ b/docs/08-Contributing/02-development.md @@ -200,6 +200,39 @@ Uninstall `Retina`: make helm-uninstall ``` +## Dependency and Security Management + +Retina uses automated dependency management and security scanning to maintain secure and up-to-date container images and dependencies. + +### Dependabot Configuration + +The repository uses [Dependabot](https://github.com/dependabot) to automatically track and update dependencies: + +- **Docker Base Images**: Automatically monitored for security updates and new versions +- **Go Modules**: Tracked for dependency updates +- **GitHub Actions**: Workflow dependencies are kept current + +#### Docker Base Image Tracking + +Retina has Dockerfiles in multiple directories, and each is tracked separately by Dependabot: + +- `/controller` - Main retina controller images (daily checks) +- `/shell` - Shell utility images (daily checks) +- `/cli` - CLI tool images (daily checks) +- `/operator` - Operator images (daily checks) +- `/test/image` - Test images (daily checks) +- `/hack/tools/kapinger` - Kapinger tool images (weekly checks) +- `/hack/tools/toolbox` - Toolbox utility images (weekly checks) + +When Dependabot detects a security vulnerability (CVE) in a base image, it will automatically create a pull request to update the image SHA to a patched version. + +### Adding New Dockerfiles + +When adding new Dockerfiles to the repository: + +1. Add the directory containing the Dockerfile to `.github/dependabot.yaml` +2. Choose an appropriate schedule: daily for critical components, weekly for tools + ## Opening a Pull Request When you're ready to open a pull request, please ensure that your branch is up-to-date with the `main` branch, updates relevant docs and tests, and passes all tests and lints. From ba2c321d2a004d53a733e0733452a9ceb87fcb58 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 21 Apr 2026 08:38:39 -0400 Subject: [PATCH 326/448] fix: migrate apiserver watcher from Endpoints to EndpointSlice (#2214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The apiserver watcher currently reads the `kubernetes` service's backing IPs via `corev1.Endpoints`, which emits a deprecation warning on v1.33+ clusters: ``` W... warnings.go:70] v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice ``` The warning is sent by the kube-apiserver as an HTTP `Warning:` response header ([KEP-1693](https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/1693-warnings/README.md)) and surfaced by the client-go warning handler; it was added in [KEP-4974](https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/4974-deprecate-endpoints) for every read/write on `Endpoints` objects in v1.33. This PR switches `ipsFromEndpoint` to list `discoveryv1.EndpointSlice` filtered by `kubernetes.io/service-name=kubernetes`, aggregating addresses across all slices (large services get split past 100 endpoints). The agent RBAC in both Helm charts is updated to grant `discovery.k8s.io/endpointslices` and drop the now-unused `core/endpoints` rules. ### Why EndpointSlice EndpointSlice is a strict superset of `Endpoints` — it supports dual-stack, traffic distribution, and scales past the 100-endpoint cap. It's been the default path for service discovery for nearly five years: | Stage | K8s version | Reference | |---|---|---| | Alpha | v1.16 | [KEP-0752](https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/0752-endpointslices/README.md), controller introduced in [#81048](https://github.com/kubernetes/kubernetes/pull/81048) | | GA — kube-proxy + controller-manager default | v1.21 (Apr 2021) | [CHANGELOG-1.21](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.21.md); kube-proxy [#103306](https://github.com/kubernetes/kubernetes/pull/103306); controller-manager [#99870](https://github.com/kubernetes/kubernetes/pull/99870) | | `v1.Endpoints` deprecated | v1.33 (Apr 2025) | [KEP-4974](https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/4974-deprecate-endpoints), [transition blog](https://kubernetes.io/blog/2025/04/24/endpoints-deprecation/) | Canonical docs: [EndpointSlices](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/). ## Related Issue N/A — surfaced during local testing on a v1.33 cluster. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary — no doc changes needed. - [x] I have added tests, if applicable. ## Testing Completed ```bash go test -tags=unit,dashboard ./pkg/watchers/apiserver/... -v -count=1 ``` All tests pass. `TestRefresh` confirms the seeded EndpointSlice IPs flow through into the created IP set. Signed-off-by: Quang Nguyen --- .../retina/templates/agent/clusterrole.yaml | 19 +++-------- .../helm/retina/templates/rbac.yaml | 14 +++----- pkg/watchers/apiserver/apiserver.go | 32 +++++++++---------- pkg/watchers/apiserver/apiserver_test.go | 19 +++++------ 4 files changed, 35 insertions(+), 49 deletions(-) diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml index ab71f1d7a6..8ab864a33a 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/clusterrole.yaml @@ -33,14 +33,13 @@ rules: - list - watch - apiGroups: - - "" + - discovery.k8s.io resources: - - namespaces - - endpoints + - endpointslices verbs: - - get - - list - - watch + - get + - list + - watch {{- if .Values.operator.enabled }} - apiGroups: - retina.sh @@ -80,14 +79,6 @@ rules: - get - patch - update - - apiGroups: - - discovery.k8s.io - resources: - - endpointslices - verbs: - - get - - list - - watch {{- end }} {{- end}} diff --git a/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml b/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml index 2f0046bf11..ff739cb724 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/rbac.yaml @@ -9,7 +9,10 @@ metadata: name: retina-cluster-reader rules: - apiGroups: [""] # "" indicates the core API group - resources: ["endpoints", "pods", "services", "replicationcontrollers", "nodes", "namespaces"] + resources: ["pods", "services", "replicationcontrollers", "nodes", "namespaces"] + verbs: ["get", "watch", "list"] + - apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] verbs: ["get", "watch", "list"] - apiGroups: ["apps"] resources: ["deployments", "replicasets"] @@ -26,15 +29,6 @@ rules: - list - watch {{- if .Values.operator.enabled }} - - apiGroups: - - "" - resources: - - namespaces - - endpoints - verbs: - - get - - list - - watch - apiGroups: - retina.sh resources: diff --git a/pkg/watchers/apiserver/apiserver.go b/pkg/watchers/apiserver/apiserver.go index defcbcf55e..d21a3f5c41 100644 --- a/pkg/watchers/apiserver/apiserver.go +++ b/pkg/watchers/apiserver/apiserver.go @@ -18,6 +18,7 @@ import ( "github.com/microsoft/retina/pkg/utils" "go.uber.org/zap" corev1 "k8s.io/api/core/v1" + discoveryv1 "k8s.io/api/discovery/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" kclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -169,9 +170,9 @@ func (a *ApiServerWatcher) initNewCache(ctx context.Context) error { return fmt.Errorf("failed to retrieve ips from kubernetes service: %w", err) } - endpointIPs, err := a.ipsFromEndpoint(ctx) + endpointIPs, err := a.ipsFromEndpointSlice(ctx) if err != nil { - return fmt.Errorf("failed to retrieve ips from kubernetes endpoint: %w", err) + return fmt.Errorf("failed to retrieve ips from kubernetes endpointslices: %w", err) } ips, err := a.resolveIPs(ctx, a.apiServerHostName) @@ -253,22 +254,21 @@ func (a *ApiServerWatcher) ipsFromService(ctx context.Context) ([]string, error) return svc.Spec.ClusterIPs, nil } -// ipsFromEndpoint retrieves IP addresses from the Endpoint resource "kubernetes" in the default namespace. -// These IPs are the addresses for the kube-apiserver. -func (a *ApiServerWatcher) ipsFromEndpoint(ctx context.Context) ([]string, error) { - ep := &corev1.Endpoints{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kubernetes", - Namespace: "default", - }, - } - if err := a.client.Get(ctx, kclient.ObjectKeyFromObject(ep), ep); err != nil { - return nil, fmt.Errorf("retrieving kubernetes endpoint: %w", err) +// ipsFromEndpointSlice retrieves IP addresses from the EndpointSlices that +// back the "kubernetes" service in the default namespace. These IPs are the +// addresses for the kube-apiserver. +func (a *ApiServerWatcher) ipsFromEndpointSlice(ctx context.Context) ([]string, error) { + var sliceList discoveryv1.EndpointSliceList + if err := a.client.List(ctx, &sliceList, + kclient.InNamespace("default"), + kclient.MatchingLabels{discoveryv1.LabelServiceName: "kubernetes"}, + ); err != nil { + return nil, fmt.Errorf("retrieving kubernetes endpointslices: %w", err) } ips := []string{} - for _, subset := range ep.Subsets { - for _, addr := range subset.Addresses { - ips = append(ips, addr.IP) + for i := range sliceList.Items { + for _, ep := range sliceList.Items[i].Endpoints { + ips = append(ips, ep.Addresses...) } } return ips, nil diff --git a/pkg/watchers/apiserver/apiserver_test.go b/pkg/watchers/apiserver/apiserver_test.go index 58659487dc..988e0641b4 100644 --- a/pkg/watchers/apiserver/apiserver_test.go +++ b/pkg/watchers/apiserver/apiserver_test.go @@ -24,6 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" corev1 "k8s.io/api/core/v1" + discoveryv1 "k8s.io/api/discovery/v1" "sigs.k8s.io/controller-runtime/pkg/client/fake" ) @@ -198,21 +199,21 @@ func getMockKubeClient() client.Client { }, } - ep := corev1.Endpoints{ + slice := discoveryv1.EndpointSlice{ ObjectMeta: metav1.ObjectMeta{ Name: "kubernetes", Namespace: "default", - }, - Subsets: []corev1.EndpointSubset{ - { - Addresses: []corev1.EndpointAddress{ - {IP: "100.64.83.200"}, - {IP: "100.64.83.201"}, - }, + Labels: map[string]string{ + discoveryv1.LabelServiceName: "kubernetes", }, }, + AddressType: discoveryv1.AddressTypeIPv4, + Endpoints: []discoveryv1.Endpoint{ + {Addresses: []string{"100.64.83.200"}}, + {Addresses: []string{"100.64.83.201"}}, + }, } - return fake.NewFakeClient(&ep, &kubernetesSvc) + return fake.NewFakeClient(&slice, &kubernetesSvc) } func TestRefreshFailsFirstFourAttemptsSucceedsOnFifth(t *testing.T) { From b662ca21c67ffcf4a0a71eb4c0831bcea2e60c10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:55:55 -0700 Subject: [PATCH 327/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.21.0 to 1.21.1 (#2223) Bumps [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) from 1.21.0 to 1.21.1.
Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/azcore's releases.

sdk/azcore/v1.21.1

1.21.1 (2026-04-16)

Bugs Fixed

  • Fixed an issue in ResponseError.Error() where the request URL path was being logged unescaped.
  • Redact query parameters when logging errors.
  • For runtime.JoinPaths, don't add a slash between root and paths when paths starts with ? (query string).

Other Changes

  • Upgraded to Go 1.25.0.
  • Upgraded dependencies.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/azcore&package-manager=go_modules&previous-version=1.21.0&new-version=1.21.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 629a008c71..81fce27d74 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ retract ( require ( cel.dev/expr v0.25.1 // indirect code.cloudfoundry.org/clock v1.0.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0 // indirect @@ -213,7 +213,7 @@ require ( require ( github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 diff --git a/go.sum b/go.sum index 493eb9a13d..d045b6e01e 100644 --- a/go.sum +++ b/go.sum @@ -69,14 +69,14 @@ github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiX github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 h1:jHb/wfvRikGdxMXYV3QG/SzUOPYN9KEUUuC0Yd0/vC0= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1/go.mod h1:pzBXCYn05zvYIrwLgtK8Ap8QcjRg+0i76tMQdWN6wOk= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 h1:fhqpLE3UEXi9lPaBRpQ6XuRW0nU7hgg4zlmZZa+a9q4= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0/go.mod h1:7dCRMLwisfRH3dBupKeNCioWYUZ4SS09Z14H+7i8ZoY= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= From 8aaa4270b6d19a883ebb6cc86103bbe3dfd45063 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:56:42 +0000 Subject: [PATCH 328/448] deps: bump github.com/mdlayher/netlink from 1.11.0 to 1.11.1 (#2224) Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.11.0 to 1.11.1.
Release notes

Sourced from github.com/mdlayher/netlink's releases.

v1.11.1

See https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md#v1111

Changelog

Sourced from github.com/mdlayher/netlink's changelog.

v1.11.1

  • [Bug Fix]: #283 fixed a bug where netlink.Conn.Receive would reject valid netlink messages whose header length is not aligned. This is common with nfqueue, nflog and conntrack events.
  • [Bug Fix]: #284 fixed a bug where netlink.Message.Data could be silently overwritten by subsequent netlink.Conn.Receive calls when netlink.Config.MessageBufferSize is enabled, due to pooled buffer reuse.
  • [Improvement]: #282 improved error handling by usage of errors package.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/mdlayher/netlink&package-manager=go_modules&previous-version=1.11.0&new-version=1.11.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 81fce27d74..2e66d2a962 100644 --- a/go.mod +++ b/go.mod @@ -241,7 +241,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 - github.com/mdlayher/netlink v1.11.0 + github.com/mdlayher/netlink v1.11.1 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c github.com/onsi/ginkgo/v2 v2.28.1 diff --git a/go.sum b/go.sum index d045b6e01e..b370badb8e 100644 --- a/go.sum +++ b/go.sum @@ -1155,8 +1155,8 @@ github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuri github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= github.com/mdlayher/netlink v1.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU= -github.com/mdlayher/netlink v1.11.0 h1:Cot7ixQZL6P/pxRFB4z3jRdGPYeZosFT+WHS3sMXy8Y= -github.com/mdlayher/netlink v1.11.0/go.mod h1:rMwDzh42W85uW3yTtiTRZFX9uway98aDQ5i+D8Jq4g4= +github.com/mdlayher/netlink v1.11.1 h1:T136gDS6Gkt+hLncaBwKdW5GpEC8Z0ykqimOebVoal0= +github.com/mdlayher/netlink v1.11.1/go.mod h1:ao4LjamyK4Uq9L8+fQzqFYpAncbeCdwbvd9Edv/pYnc= github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= github.com/mdlayher/socket v0.6.0 h1:ScZPaAGyO1icQnbFrhPM8mnXyMu9qukC1K4ZoM2IQKU= From 9d92dc3315a1b76fe816c49d5c568338773bc737 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:57:06 +0000 Subject: [PATCH 329/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.99.0 to 1.99.1 (#2226) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.99.0 to 1.99.1.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.99.0&new-version=1.99.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 2e66d2a962..23d8eedee4 100644 --- a/go.mod +++ b/go.mod @@ -44,15 +44,15 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect @@ -227,7 +227,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.41.6 github.com/aws/aws-sdk-go-v2/config v1.32.16 github.com/aws/aws-sdk-go-v2/credentials v1.19.15 - github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9 diff --git a/go.sum b/go.sum index b370badb8e..670622700e 100644 --- a/go.sum +++ b/go.sum @@ -259,8 +259,8 @@ github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM= github.com/aws/aws-sdk-go-v2/config v1.32.16/go.mod h1:duCCnJEFqpt2RC6no1iK6q+8HpwOAkiUua0pY507dQc= github.com/aws/aws-sdk-go-v2/credentials v1.19.15 h1:fyvgWTszojq8hEnMi8PPBTvZdTtEVmAVyo+NFLHBhH4= @@ -281,16 +281,16 @@ github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 h1:XJ/AEFYj9VFPJdF+VFi4SU github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2/go.mod h1:JUBHdhvKbbKmhaHjLsKJAWnQL80T6nURmhB/LEprV+4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= -github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1 h1:kU/eBN5+MWNo/LcbNa4hWDdN76hdcd7hocU5kvu7IsU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 h1:a1Fq/KXn75wSzoJaPQTgZO0wHGqE9mjFnylnqEPTchA= github.com/aws/aws-sdk-go-v2/service/signin v1.0.10/go.mod h1:p6+MXNxW7IA6dMgHfTAzljuwSKD0NCm/4lbS4t6+7vI= github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 h1:x6bKbmDhsgSZwv6q19wY/u3rLk/3FGjJWyqKcIRufpE= From 7250d9c473e5861df994385025e3b24cd12b6cd1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:57:28 +0000 Subject: [PATCH 330/448] deps: bump k8s.io/metrics from 0.35.3 to 0.35.4 (#2204) Bumps [k8s.io/metrics](https://github.com/kubernetes/metrics) from 0.35.3 to 0.35.4.
Commits
  • 2dd2b8a Update dependencies to v0.35.4 tag
  • f34cd81 Merge pull request #138356 from dims/update-moby-spdystream-v0.5.1-1.35
  • d571fcb Update github.com/moby/spdystream from v0.5.0 to v0.5.1
  • See full diff in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 23d8eedee4..d3c6321b81 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/prometheus/client_golang v1.23.2 github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.27.1 - k8s.io/client-go v0.35.3 + k8s.io/client-go v0.35.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 ) @@ -201,8 +201,8 @@ require ( golang.org/x/term v0.42.0 // indirect google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.35.3 - k8s.io/apimachinery v0.35.3 + k8s.io/api v0.35.4 + k8s.io/apimachinery v0.35.4 k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 @@ -266,7 +266,7 @@ require ( k8s.io/apiextensions-apiserver v0.35.3 k8s.io/cli-runtime v0.35.3 k8s.io/kubectl v0.35.3 - k8s.io/metrics v0.35.3 + k8s.io/metrics v0.35.4 k8s.io/perf-tests/network/benchmarks/netperf v0.0.0-00010101000000-000000000000 sigs.k8s.io/controller-runtime v0.23.3 ) @@ -679,7 +679,7 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect honnef.co/go/tools v0.7.0 // indirect - k8s.io/code-generator v0.35.3 // indirect + k8s.io/code-generator v0.35.4 // indirect k8s.io/component-helpers v0.35.3 // indirect k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect lukechampine.com/blake3 v1.2.1 // indirect diff --git a/go.sum b/go.sum index 670622700e..e63c949746 100644 --- a/go.sum +++ b/go.sum @@ -1993,20 +1993,20 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= -k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= -k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= +k8s.io/api v0.35.4 h1:P7nFYKl5vo9AGUp1Z+Pmd3p2tA7bX2wbFWCvDeRv988= +k8s.io/api v0.35.4/go.mod h1:yl4lqySWOgYJJf9RERXKUwE9g2y+CkuwG+xmcOK8wXU= k8s.io/apiextensions-apiserver v0.35.3 h1:2fQUhEO7P17sijylbdwt0nBdXP0TvHrHj0KeqHD8FiU= k8s.io/apiextensions-apiserver v0.35.3/go.mod h1:tK4Kz58ykRpwAEkXUb634HD1ZAegEElktz/B3jgETd8= -k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= -k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apimachinery v0.35.4 h1:xtdom9RG7e+yDp71uoXoJDWEE2eOiHgeO4GdBzwWpds= +k8s.io/apimachinery v0.35.4/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc= k8s.io/apiserver v0.35.3 h1:D2eIcfJ05hEAEewoSDg+05e0aSRwx8Y4Agvd/wiomUI= k8s.io/apiserver v0.35.3/go.mod h1:JI0n9bHYzSgIxgIrfe21dbduJ9NHzKJ6RchcsmIKWKY= k8s.io/cli-runtime v0.35.3 h1:UZq4ipNimtzBmhN7PPKbfAdqo8quK0H0UdGl6qAQnqI= k8s.io/cli-runtime v0.35.3/go.mod h1:O7MUmCqcKSd5xI+O5X7/pRkB5l0O2NIhOdUVwbHLXu4= -k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= -k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= -k8s.io/code-generator v0.35.3 h1:NDGCLkEm6Ho65wTdSe2EgErmmtsrezOPwwOchlNc6FQ= -k8s.io/code-generator v0.35.3/go.mod h1:LAVriRGXQusHQ0Ns64SE1ublSswm1KrK7cXn0GuQETg= +k8s.io/client-go v0.35.4 h1:DN6fyaGuzK64UvnKO5fOA6ymSjvfGAnCAHAR0C66kD8= +k8s.io/client-go v0.35.4/go.mod h1:2Pg9WpsS4NeOpoYTfHHfMxBG8zFMSAUi4O/qoiJC3nY= +k8s.io/code-generator v0.35.4 h1:i0FfiXAeUMBlHarjVk5ZWf6Wjsg3YJpNYmOg0nPk6r4= +k8s.io/code-generator v0.35.4/go.mod h1:rwLDdemFgPK6dGlLFHPUieyekgAlV1x8IVafjAy/ELA= k8s.io/component-base v0.35.3 h1:mbKbzoIMy7JDWS/wqZobYW1JDVRn/RKRaoMQHP9c4P0= k8s.io/component-base v0.35.3/go.mod h1:IZ8LEG30kPN4Et5NeC7vjNv5aU73ku5MS15iZyvyMYk= k8s.io/component-helpers v0.35.3 h1:Rl2p3wNMC0YU21rziLkWXavr7MwkB5Td3lNZ/+gYGm8= @@ -2019,8 +2019,8 @@ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= k8s.io/kubectl v0.35.3 h1:1KqSYXk/sodU7VeDvK6atX2kAGUZd2QTeR5K7Hb9r9w= k8s.io/kubectl v0.35.3/go.mod h1:GPHxZqRe+u/i3gTBoVQHeIyq2NilfNPj9hDWeuN3x5s= -k8s.io/metrics v0.35.3 h1:WonA18pEwrtb7a6XfhFg1ZY1Le0RFkcEw7CFApMTZos= -k8s.io/metrics v0.35.3/go.mod h1:/O8UBb5QVyAekR2QvL/WWxskpdV1wVSEl4MSLAy4Ql4= +k8s.io/metrics v0.35.4 h1:KFo3xFe5rzLDarHLNjZB0J1g1c5fvl6A5Kk/8KzIwOA= +k8s.io/metrics v0.35.4/go.mod h1:5DO36o9esGC1VXylSpqJWmwhoopS/erADQcACz1tN3s= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= From 9488f9ddaccf6dc9565d91b89d3e5f25b722af70 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 21 Apr 2026 17:07:09 -0400 Subject: [PATCH 331/448] deps: pin Docker base images with tag and digest (#2228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Follow-up to #1885. Every `FROM` line in the repo's Dockerfiles pins only the digest (`image@sha256:...`) with the tag documented in an adjacent `# skopeo inspect` comment. Dependabot doesn't read the comments — with no tag on the `FROM`, it tracks the "latest" digest for the repository name and bumps blindly, ignoring which variant the pinned digest actually belongs to. This is already producing broken PRs. In #2220, the Windows Server Core `golang` digest in `controller/Dockerfile.windows-cgo` and `controller/Dockerfile.windows-native` was replaced with the `azurelinux3.0` digest used by the Linux images — those FROMs wouldn't build. ## Fix Per [Dependabot's docs](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file), when a `FROM` has both a tag and a digest, Dependabot only bumps the digest within that tag. Switching every `FROM` to `image:tag@sha256:digest` scopes each variant separately (`1.26.2-azurelinux3.0`, plain `1.26.2`, `1.26.2-windowsservercore-ltsc2022`, `windows/servercore:ltsc2022`, etc.) and yields readable PR titles like `bump golang from 1.26.2-azurelinux3.0 to 1.27.0-azurelinux3.0` instead of `` bump golang from `33d887d` to `8fe67ba` ``. While here, each digest is refreshed to the current `skopeo inspect` result for its tag. - **Scope**: 25 `FROM` lines across 14 Dockerfiles (`controller/`, `operator/`, `cli/`, `shell/`, `test/image/`, `hack/tools/{kapinger,toolbox}/`). - **Digest refresh**: 5 of 8 unique `image:tag` combinations had newer digests upstream; 3 (`azurelinux/base/core:3.0`, `azurelinux/distroless/minimal:3.0`, `mirror/docker/library/ubuntu:24.04`) were unchanged. - **Follow-up**: the 6 open Dependabot PRs #2216–#2221 should be closed; the next run will regenerate correctly-scoped PRs per tag. ## Related Issue Follow-up to #1885. No issue to close. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed N/A — config-only change. ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- cli/Dockerfile | 8 ++++---- controller/Dockerfile | 6 +++--- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-2022 | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 4 ++-- controller/Dockerfile.windows-retina-oss-build | 2 +- hack/tools/kapinger/Dockerfile | 6 +++--- hack/tools/toolbox/Dockerfile | 4 ++-- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2022 | 4 ++-- shell/Dockerfile | 2 +- test/image/Dockerfile | 2 +- 14 files changed, 25 insertions(+), 25 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index dfa03a15b9..df184ff3ee 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,11 +25,11 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # minimal libs stage — provides only the system libraries needed by the CGO-enabled binary, # without the bloat of the full Go SDK image (python, gcc, systemd, etc.) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS libs +FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS libs # Target 1: Distroless (secure, minimal) # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS distroless-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS distroless-target COPY --from=libs /lib/ /lib COPY --from=libs /usr/lib/ /usr/lib COPY --from=libs /etc/pki/tls/ /etc/pki/tls/ @@ -38,7 +38,7 @@ COPY --from=builder /workspace/kubectl-retina . # Target 2: Shell-enabled (operational, init container support) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS shell-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS shell-target WORKDIR / COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina RUN chmod +x /bin/kubectl-retina diff --git a/controller/Dockerfile b/controller/Dockerfile index 104a9ed064..ad9765ad93 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,13 +1,13 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS azurelinux-distroless +FROM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS azurelinux-distroless # build stages diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 1ac47bc8f9..dcff50b3df 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 4ebc4430cd..e4fa7ece80 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index 3341d93cb3..fc9aa2c5c7 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,6 +1,6 @@ # pinned base image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:d4c6d1a8a1a306b12691c3b2e5e3a8bfad786cbd6b7831cd74a9a6a99eab08ad AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:e000e9a1712065a0218447c20ae19984b447fa741d11cf64696b8a1172fcd7da AS ltsc2022 FROM ltsc2022 AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 65ac9d60c7..d8958f95fa 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:3668c2f2d838ebf8d03885e71c6bf309a66b1107a926f0e59c3d9ed1ef150a72 AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:a17b1a89b70de1af2f5529b851e78fa3d4d1af125686164023e978f4b3beb69e AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 316828a9b6..3873bcd059 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang@sha256:3668c2f2d838ebf8d03885e71c6bf309a66b1107a926f0e59c3d9ed1ef150a72 AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:a17b1a89b70de1af2f5529b851e78fa3d4d1af125686164023e978f4b3beb69e AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver@sha256:be41510eb214c55def9162ef1fb5e71f1b71ce4d64d91bc963199f2383e034ea AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver:ltsc2022@sha256:3680dad0bb773da8efcd9d928eaf4e33817875ab71a43792640ab1bcc0b3c074 AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index 4688e32709..ab4b5d8b84 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -3,7 +3,7 @@ ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:d4c6d1a8a1a306b12691c3b2e5e3a8bfad786cbd6b7831cd74a9a6a99eab08ad AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:e000e9a1712065a0218447c20ae19984b447fa741d11cf64696b8a1172fcd7da AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index ccfb6f3080..46fd7258fa 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8d219d3f8e6edc46cc6d1f4bec61347560c2bca6ba53c4eae908c542fbc72a65 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:6c27ae470941ef215b3eea86fcd6632a7ab975f391e5a75f546d3a76fd686705 AS builder WORKDIR /build ADD . . @@ -17,7 +17,7 @@ CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8d219d3f8e6edc46cc6d1f4bec61347560c2bca6ba53c4eae908c542fbc72a65 AS windows-builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:6c27ae470941ef215b3eea86fcd6632a7ab975f391e5a75f546d3a76fd686705 AS windows-builder WORKDIR /build ADD . . @@ -25,7 +25,7 @@ RUN go mod download RUN GOOS=windows go build -o kapinger.exe . # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore@sha256:d4c6d1a8a1a306b12691c3b2e5e3a8bfad786cbd6b7831cd74a9a6a99eab08ad AS windows +FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:e000e9a1712065a0218447c20ae19984b447fa741d11cf64696b8a1172fcd7da AS windows WORKDIR /app COPY --from=windows-builder /build/kapinger.exe . ENTRYPOINT [ "cmd.exe" ] diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 3609abbd06..129719f4eb 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,11 +1,11 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:8d219d3f8e6edc46cc6d1f4bec61347560c2bca6ba53c4eae908c542fbc72a65 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:6c27ae470941ef215b3eea86fcd6632a7ab975f391e5a75f546d3a76fd686705 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . # skopeo inspect docker://mcr.microsoft.com/mirror/docker/library/ubuntu:24.04 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/mirror/docker/library/ubuntu@sha256:c35e29c9450151419d9448b0fd75374fec4fff364a27f176fb458d472dfc9e54 +FROM mcr.microsoft.com/mirror/docker/library/ubuntu:24.04@sha256:c35e29c9450151419d9448b0fd75374fec4fff364a27f176fb458d472dfc9e54 RUN apt-get update RUN apt-get install -y \ axel \ diff --git a/operator/Dockerfile b/operator/Dockerfile index 691fa19903..e734072aa5 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder ARG VERSION ARG APP_INSIGHTS_ID @@ -25,7 +25,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ ##################### controller ####################### # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index dcb0a5a778..9c7f0a9dee 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder # Build args ARG VERSION @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver@sha256:be41510eb214c55def9162ef1fb5e71f1b71ce4d64d91bc963199f2383e034ea +FROM mcr.microsoft.com/windows/nanoserver:ltsc2022@sha256:3680dad0bb773da8efcd9d928eaf4e33817875ab71a43792640ab1bcc0b3c074 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 diff --git a/shell/Dockerfile b/shell/Dockerfile index c885460ef2..deedfdb9be 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b +FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b RUN tdnf install -y \ bind-utils \ diff --git a/test/image/Dockerfile b/test/image/Dockerfile index f3847464af..3d1edbe381 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:33d887d995c314d0efbc0e8693a6821495f7b1b92516316fd9c8b43f74579dbd AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 14538344ad878c7ed5b058fad264b4b82fb9e834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Larivi=C3=A8re?= Date: Tue, 21 Apr 2026 17:33:27 -0400 Subject: [PATCH 332/448] feat(chart): Add HTTPRoute support for hubble-ui (#2193) # Description Add HTTPRoute support for hubble-ui for clusters using Gateway API ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .../retina/templates/hubble-ui/httproute.yaml | 44 +++++++++++++++++++ .../controller/helm/retina/values.yaml | 19 +++++++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/httproute.yaml diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/httproute.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/httproute.yaml new file mode 100644 index 0000000000..28899ca991 --- /dev/null +++ b/deploy/hubble/manifests/controller/helm/retina/templates/hubble-ui/httproute.yaml @@ -0,0 +1,44 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.hubble.ui.httpRoute.enabled }} +{{- $baseUrl := .Values.hubble.ui.baseUrl -}} +{{- $port := .Values.hubble.ui.httpRoute.port | default .Values.hubble.ui.service.port | default 80 -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: hubble-ui + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-ui + app.kubernetes.io/name: hubble-ui + app.kubernetes.io/part-of: cilium + {{- with .Values.hubble.ui.httpRoute.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if or .Values.hubble.ui.httpRoute.annotations .Values.hubble.ui.annotations }} + annotations: + {{- with .Values.hubble.ui.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.hubble.ui.httpRoute.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + {{- if .Values.hubble.ui.httpRoute.parentRefs }} + parentRefs: + {{- toYaml .Values.hubble.ui.httpRoute.parentRefs | nindent 4 }} + {{- end }} + {{- if .Values.hubble.ui.httpRoute.hostnames }} + hostnames: + {{- range .Values.hubble.ui.httpRoute.hostnames }} + - {{ . }} + {{- end }} + {{- end }} + rules: + - matches: + - path: + type: PathPrefix + value: {{ $baseUrl | quote }} + backendRefs: + - name: hubble-ui + port: {{ $port }} +{{- end }} diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 10954f56dd..0967106ab8 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -128,7 +128,7 @@ securityContext: - SYS_ADMIN - SYS_RESOURCE # for setting rlimit - NET_ADMIN # for packetparser plugin - - IPC_LOCK # for mmap() calls made by NewReader(), ref: https://man7.org/linux/man-pages/man2/mmap.2.html + - IPC_LOCK # for mmap() calls made by NewReader(), ref: https://man7.org/linux/man-pages/man2/mmap.2.html windowsOptions: runAsUserName: "NT AUTHORITY\\SYSTEM" @@ -831,6 +831,23 @@ hubble: # hosts: # - chart-example.local + # -- hubble-ui HTTPRoute configuration (Gateway API). + # Requires Kubernetes 1.26+ or Gateway API CRDs to be pre-installed. + httpRoute: + enabled: false + annotations: {} + labels: {} + # -- Parent Gateways that this route is attached to. + parentRefs: + - name: example-gateway + namespace: default + sectionName: example-listener + # -- Hostnames for this HTTPRoute. + hostnames: + - chart-example.local + # -- Backend port number. Defaults to the service port (80). + port: ~ + # -- Hubble flows export. export: # --- Defines max file size of output file before it gets rotated. From ed715a27b3afd173486955b4d5255e80d7089aef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:13:13 -0400 Subject: [PATCH 333/448] deps: bump github.com/cilium/ebpf from 0.20.1-0.20260218191617-ee67e7f43dd9 to 0.21.0 (#2225) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/cilium/ebpf](https://github.com/cilium/ebpf) from 0.20.1-0.20260218191617-ee67e7f43dd9 to 0.21.0.
Release notes

Sourced from github.com/cilium/ebpf's releases.

v0.21.0: Struct Ops, Weak Symbols and BTF deduplication

Hi, everyone! The Cilium project is proud to announce v0.21.0 of ebpf-go, our first major 2026 feature release. Please note that this version comes with a few breaking changes for XDP users that may require some intervention based on your use case, so please read the following section carefully before upgrading! We've also removed some long-deprecated APIs.

Breaking changes

XDP Attach Type

This release saw a change to the ELF parsing logic, specifically to XDP programs. Previously, XDP programs had their ProgramSpec.AttachType set to AttachNone. Prompted by upstream changes in Linux 6.18, XDP programs now come with an AttachXDP attach type. This change ensures compatibility with kernels going forward, as well as better interoperability with libbpf-based tools using shared PROG_ARRAY maps.

tl;dr: Linux 6.18 and later disallows mixing attach types within the same program array.

If your application uses a pinned program array, you may need to manually change the attach type of your XDP programs to AttachNone before they are loaded to ensure they can still be inserted into maps containing pre-upgrade programs.

The same goes for BPF links. If you're updating an XDP link created by an older version of ebpf-go, you need to ensure your XDP program is loaded with the same attach type the link was initially created with, or updating will fail with EINVAL.

For an example of how to deal with this change, here's the the Cilium PR that implemented logic to try both attach types when updating links.

Windows helper function rename

ebpf-for-windows was upgraded from 0.21.0 to v1.0.0-rc1. efW made breaking changes to the names of helper functions, our API has been updated to match:

New Features

  • Struct ops — The ELF reader can now parse struct ops sections, building MapSpecs and resolving function-pointer members. link.AttachStructOps has been added to allow attaching a StructOpsMap as a link. A sched_ext example can be found here.
  • Weak symbol & ELF linking — Programs and maps defined as weak symbols are now fully supported. The ELF reader performs per-symbol decoding for both ProgramSpec and MapSpec, meaning linked objects (produced via bpftool gen object) are now handled correctly.
  • BTF type deduplication — btf.Builder can now deduplicate types while generating a BTF blob. Deduplication can be enabled by passing BuilderOptions to NewBuilder with the Deduplication field set to true.
  • ProgramSpec.Compatible was added — ProgramSpec.Tag is now deprecated. The new ProgramSpec.Compatible method compares a loaded program's tag against both SHA-1 and SHA-256 hashes of the spec, ensuring correct behaviour across kernels — including kernel v6.18+, which switched to SHA-256 for program hashing.
  • ProgramInfo improvements — The program name as reported by ProgramInfo.Name is now sourced from BTF func info when available to provide the full program name if it's longer than 15 bytes.
  • LinkInfo improvements — Added a number of methods and types related to reading back link info.
  • Reverse symbol lookup — Added Executable.Symbol to resolve addresses to a symbol and relative offset.
  • Uprobe/kprobe link feature probing — HaveBPFLinkKprobeMulti, HaveBPFLinkUprobeMulti, and HaveBPFLinkKprobeSession are now exported from the features package, making it easier to probe for multi-attach support before loading programs.
  • Program run batching — A new RunOptions.BatchSize option has been added to support batching when running programs.

Bug Fixes

  • Allow weak kfuncs loading without CAP_SYS_ADMIN — Loading programs with weak kfuncs on kernels that don't have the kfunc no longer fails with "operation not permitted" when the caller lacks CAP_SYS_ADMIN. The permission error is now treated as "not found" for weak kfuncs.
  • ELF reader nil panic — Fixed a panic that could occur when loading an ELF without BTF due to a nil extInfo pointer. Along with the fix, a suite of regression tests was added that exercises the core loader logic with non-BTF ELFs as well.
  • QueryResult.HaveLinkInfo heuristic — The heuristic has been updated to check for at least one attached program with a non-zero link ID, fixing a false positive introduced by a kernel change that began populating the revision field for cgroup queries.
  • Windows map/program count — Increased the default map and program count on Windows to reduce failures when loading collections with more maps than previously allocated.

More breaking changes

Deprecations

In this release we have removed a number of features which had been deprecated for a while.

... (truncated)

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d3c6321b81..33e5092b5e 100644 --- a/go.mod +++ b/go.mod @@ -230,7 +230,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 - github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9 + github.com/cilium/ebpf v0.21.0 github.com/cilium/hive v0.0.0-20260108104938-97756f6ff54c github.com/cilium/proxy v0.0.0-20250623105955-2136f59a4ea1 github.com/cilium/workerpool v1.3.0 diff --git a/go.sum b/go.sum index e63c949746..56cd75606d 100644 --- a/go.sum +++ b/go.sum @@ -404,8 +404,8 @@ github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a/go.mod h1:/7LC2GOgyX github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk= -github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9 h1:hQW7n5ePt/HDgeZLcyT3pFENyfa6vmaGU7M+tq2pa64= -github.com/cilium/ebpf v0.20.1-0.20260218191617-ee67e7f43dd9/go.mod h1:EGj6HpG/oejvbTAsMWwlA4UbMU7WBAgILd+9OSvcDTc= +github.com/cilium/ebpf v0.21.0 h1:4dpx1J/B/1apeTmWBH5BkVLayHTkFrMovVPnHEk+l3k= +github.com/cilium/ebpf v0.21.0/go.mod h1:1kHKv6Kvh5a6TePP5vvvoMa1bclRyzUXELSs272fmIQ= github.com/cilium/fake v0.7.0 h1:4EKBtTweQrJoD4q45qDGu8udulmYMo48Y0BhEbrB1jc= github.com/cilium/fake v0.7.0/go.mod h1:hA1YsEjgIs5Gdeq/DVrDWGuhLCoVok7THTvQaGDO5bc= github.com/cilium/hive v0.0.0-20260108104938-97756f6ff54c h1:mP/Z+oVplgbg3oV1lwsAC86NPLWioN/TqlmZ6+BI2I0= From 55709811c6ffca1d4ffa6d25b3c7365355b1b19d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:49:04 -0400 Subject: [PATCH 334/448] deps: bump github.com/cilium/workerpool from 1.3.0 to 1.4.0 (#2227) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/cilium/workerpool](https://github.com/cilium/workerpool) from 1.3.0 to 1.4.0.
Release notes

Sourced from github.com/cilium/workerpool's releases.

v1.4.0

What's Changed

Enhancements

Documentation

CI

New Contributors

Full Changelog: https://github.com/cilium/workerpool/compare/v1.3.0...v1.4.0

Commits
  • 0998340 doc: explicit that result callback cannot call Submit() nor Close()
  • d7b7562 doc: improve readme to more clearly state the lib purpose, pros and cons
  • 8427060 doc: enable godoclint and address reported issues
  • 6ecdd96 doc: ensure example_test.go and the example in the readme are in sync
  • bd12cf2 doc: improve doc and examples around task context cancellation
  • 308f6da doc: improve doc around using Drain when WithResultCallback is used
  • acd1f0d doc: improve doc around the usage and interraction of Close and Drain
  • 99bd3ba improve comments that explain why no lock is needed around wp.results
  • 5570790 doc: make the for loop condition in the examples more readable
  • e29e14a add WithResultCallback option to avoid unbounded result accumulation
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 33e5092b5e..0dcc8cc513 100644 --- a/go.mod +++ b/go.mod @@ -233,7 +233,7 @@ require ( github.com/cilium/ebpf v0.21.0 github.com/cilium/hive v0.0.0-20260108104938-97756f6ff54c github.com/cilium/proxy v0.0.0-20250623105955-2136f59a4ea1 - github.com/cilium/workerpool v1.3.0 + github.com/cilium/workerpool v1.4.0 github.com/florianl/go-tc v0.4.8 github.com/go-logr/zapr v1.3.0 github.com/google/gopacket v1.1.19 diff --git a/go.sum b/go.sum index 56cd75606d..260cb7f14c 100644 --- a/go.sum +++ b/go.sum @@ -418,8 +418,8 @@ github.com/cilium/statedb v0.5.6 h1:qid1eoMlWAYi02qMHL9Ewdhtd+FCoTF6nGUrcBB36to= github.com/cilium/statedb v0.5.6/go.mod h1:utZbqAU8l3X/2zmbBwoYC2KuRTstuSqo+c4cw4jXsCM= github.com/cilium/stream v0.0.1 h1:82zuM/WwkLiac2Jg5FrzPxZHvIBbxXTi4VY7M+EYLs0= github.com/cilium/stream v0.0.1/go.mod h1:/e83AwqvNKpyg4n3C41qmnmj1x2G9DwzI+jb7GkF4lI= -github.com/cilium/workerpool v1.3.0 h1:7BhHxoqNtpqtmce6MxZdgWODze4lYHbWkEUQ+3xEu8M= -github.com/cilium/workerpool v1.3.0/go.mod h1:0evs6P39nORTphjRtTtHLXTyCPQUwelXCK4wBJmVP7g= +github.com/cilium/workerpool v1.4.0 h1:Tn0e2Ie1THjepOnj5PobkhZ3CLknostEcKRvEGvbY/Y= +github.com/cilium/workerpool v1.4.0/go.mod h1:0evs6P39nORTphjRtTtHLXTyCPQUwelXCK4wBJmVP7g= github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= From 1c822ac8c28b69ee95aa5e5330714cd253baaace Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:03:58 -0400 Subject: [PATCH 335/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.17.0 to 0.18.0 (#2222) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.17.0 to 0.18.0.
Commits
  • 739c700 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore (#10197)
  • 237b5a3 build(deps): bump the all group with 2 updates (#10200)
  • bd28182 build(deps): bump the all group in /kubetest2-aks with 2 updates (#10196)
  • 7d45437 build(deps): bump github.com/go-git/go-git/v5 in /kubetest2-aks (#10193)
  • b30c992 chore: pin labeler GitHub Action to full-length commit SHAs (#10192)
  • e188952 build(deps): bump oss/go/microsoft/golang in the all group (#10178)
  • 970bd8e Merge pull request #10189 from andyzhangx/fix/cross-rg-private-dns-zone
  • c6c8ff5 fix: capitalize DNS in error message, add PrivateDNSZoneID RG assertion in test
  • bbc7a91 fix: use single consistent 'resourceGroup' log key, remove duplicates
  • bb06c6c fix: improve error messages and preserve log key backward compatibility
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0dcc8cc513..675467f0b1 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.27.1 k8s.io/client-go v0.35.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 ) diff --git a/go.sum b/go.sum index 260cb7f14c..5f4197cc9a 100644 --- a/go.sum +++ b/go.sum @@ -2033,8 +2033,8 @@ oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0 h1:2dTd+O9qw29HmFJLM1ndXFzZHgsHSMjypZut4Aswrtg= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.17.0/go.mod h1:/9zZbyG796jn0eDbnf7arSRHwj+CxObf1Mvln/+UbVs= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0 h1:RuMG+Vi+tss3+wkWdZijb9Oh06bR1LYpYGx7bCsMays= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0/go.mod h1:3exQL0c2uraRFH64nTYNvTYAeEwyglaj3X/BIvxaDU4= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 h1:lJR9oMwgaUvKqWp+Pt2F/dpqEpiU8PpxELV5cA65rGE= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0/go.mod h1:xSnyMWmeA+LeCdpM15e56eZZOVjd4SXUVvFrfSQISdI= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= From bc19b86b94572c332b6d09caac74749f32e4cdaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 12:52:38 -0400 Subject: [PATCH 336/448] deps: bump aquasecurity/trivy-action from 0.35.0 to 0.36.0 (#2230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.35.0 to 0.36.0.
Release notes

Sourced from aquasecurity/trivy-action's releases.

v0.36.0

What's Changed

New Contributors

Full Changelog: https://github.com/aquasecurity/trivy-action/compare/v0.35.0...v0.36.0

Commits
  • ed142fd chore: update action version to v0.36.0 in examples (#563)
  • dea62cf chore(deps): Update trivy to v0.70.0 (#559)
  • 128d9a8 chore: use GitHub Actions as git commit author in bump-trivy workflow (#561)
  • 876cf04 Upgrade Trivy action version from 0.33.1 to 0.35.0 fixes #549 (#548)
  • dada784 Fix typo in GOOGLE_APPLICATION_CREDENTIALS env var name (#547)
  • 4a2deec fix: use portable shebang in entrypoint.sh (#545)
  • 1994662 chore(deps): bump the actions group with 5 updates (#558)
  • 6b36659 chore: add zizmor config (#557)
  • 316aa5a ci: add dependabot config (#556)
  • 264c9c5 test: use pinned digests for trivy-db, trivy-java-db and trivy-checks (#555)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aquasecurity/trivy-action&package-manager=github_actions&previous-version=0.35.0&new-version=0.36.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index f84580c205..6aea486a5f 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -39,7 +39,7 @@ jobs: echo "TAG=$TAG" >> $GITHUB_ENV - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # 0.36.0 with: image-ref: "ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ env.TAG }}" format: "template" From 75d71ea939c28195075acb6776fac6a92e3dc0fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 13:49:54 -0400 Subject: [PATCH 337/448] deps: bump oss/go/microsoft/golang from `eb3ce81` to `d904c53` in /test/image (#2231) Bumps oss/go/microsoft/golang from `eb3ce81` to `d904c53`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 3d1edbe381..7bb08f4e5c 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From c27b5e35f92db6996688787ef54f61ac0e39e016 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 20:01:14 -0400 Subject: [PATCH 338/448] deps: bump oss/go/microsoft/golang from `eb3ce81` to `d904c53` in /controller (#2232) Bumps oss/go/microsoft/golang from `eb3ce81` to `d904c53`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-windowsservercore-ltsc2022&new-version=1.26.2-windowsservercore-ltsc2022)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index ad9765ad93..be763d4461 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index dcff50b3df..135e98ac86 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index e4fa7ece80..95b020223d 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index d8958f95fa..028dcb15a2 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:a17b1a89b70de1af2f5529b851e78fa3d4d1af125686164023e978f4b3beb69e AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:ebf83c70a353e25631b0d52fafa8f8e12c37b66dfba20641a58044d6df9059fb AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 3873bcd059..90134d444e 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:a17b1a89b70de1af2f5529b851e78fa3d4d1af125686164023e978f4b3beb69e AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:ebf83c70a353e25631b0d52fafa8f8e12c37b66dfba20641a58044d6df9059fb AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . From 5981b2ea80c77a9b932655a6a8923510f8da2322 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:17:31 -0400 Subject: [PATCH 339/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.99.1 to 1.100.0 (#2238) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.99.1 to 1.100.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.99.1&new-version=1.100.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 675467f0b1..4d43b91c59 100644 --- a/go.mod +++ b/go.mod @@ -227,7 +227,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.41.6 github.com/aws/aws-sdk-go-v2/config v1.32.16 github.com/aws/aws-sdk-go-v2/credentials v1.19.15 - github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1 + github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 github.com/cilium/ebpf v0.21.0 diff --git a/go.sum b/go.sum index 5f4197cc9a..a658f86c05 100644 --- a/go.sum +++ b/go.sum @@ -289,8 +289,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53R github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1 h1:kU/eBN5+MWNo/LcbNa4hWDdN76hdcd7hocU5kvu7IsU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.99.1/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 h1:a1Fq/KXn75wSzoJaPQTgZO0wHGqE9mjFnylnqEPTchA= github.com/aws/aws-sdk-go-v2/service/signin v1.0.10/go.mod h1:p6+MXNxW7IA6dMgHfTAzljuwSKD0NCm/4lbS4t6+7vI= github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 h1:x6bKbmDhsgSZwv6q19wY/u3rLk/3FGjJWyqKcIRufpE= From 4493c3233c76348eacb6fc2bca3607305dd3e41f Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 23 Apr 2026 12:46:16 -0400 Subject: [PATCH 340/448] chore(deps): consolidate dependabot config with groups and cooldowns (#2245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Currently the Dependabot config has 7 separate Docker blocks (one per Dockerfile directory) running daily, no dependency grouping for gomod, and no tracking for the `/site` npm packages. This generates ~9 individual PRs/week and misses Docusaurus version updates entirely. This PR consolidates and optimizes `.github/dependabot.yaml`: - **Docker**: Collapse 7 blocks into 1 using multi-directory `directories:` syntax, switch from daily to weekly, and group by image family (`golang-base`, `azurelinux-base`, `windows-base`, `ubuntu-base`) - **Go modules**: Add patch-only groups for `k8s`, `cilium`, `aws-sdk`, `azure-sdk`, and `otel` families — minors and majors remain standalone for review - **GitHub Actions**: Add `actions-patch` group for patch-only bundling - **npm**: Add `/site` (Docusaurus) tracking with weekly schedule and `docusaurus` group for `@docusaurus/*` / `@mdx-js/*` patches - **Cooldowns**: 7d default / 30d major for Docker and gomod; 3d / 14d for actions; 7d / 30d for npm - **Cleanup**: Remove `inspektor-gadget` ignore (no longer used) ## Related Issue N/A ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. (config-only change) - [ ] I have added tests, if applicable. (config-only change) ## Screenshots (if applicable) or Testing Completed N/A — config-only change. ## Additional Notes - `directories:` (plural) requires GitHub-hosted Dependabot (which this repo uses). See [GitHub changelog](https://github.blog/changelog/2024-06-25-simplified-dependabot-yml-configuration-with-multi-directory-key-directories-and-wildcard-glob-support/). - Security updates bypass cooldown windows automatically — no CVE delay risk. - Docker groups deliberately don't restrict `update-types` since digest-only re-pins don't reliably classify as "patch" in Dependabot's semver model. Signed-off-by: Quang Nguyen --- .github/dependabot.yaml | 145 ++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 66 deletions(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index b3f317a945..73a543a3d1 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -1,48 +1,39 @@ version: 2 updates: - # Docker base image tracking - Critical components (daily) + # Docker base images across all Dockerfiles - package-ecosystem: "docker" - directory: "/controller" + directories: + - "/controller" + - "/shell" + - "/cli" + - "/operator" + - "/test/image" + - "/hack/tools/kapinger" + - "/hack/tools/toolbox" schedule: - interval: "daily" - reviewers: - - "microsoft/retina" - commit-message: - prefix: "deps" - labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 5 - - package-ecosystem: "docker" - directory: "/shell" - schedule: - interval: "daily" - reviewers: - - "microsoft/retina" - commit-message: - prefix: "deps" - labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 5 - - package-ecosystem: "docker" - directory: "/cli" - schedule: - interval: "daily" - reviewers: - - "microsoft/retina" - commit-message: - prefix: "deps" - labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 5 - - package-ecosystem: "docker" - directory: "/operator" - schedule: - interval: "daily" + interval: "weekly" reviewers: - "microsoft/retina" commit-message: prefix: "deps" labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 5 - - package-ecosystem: "docker" - directory: "/test/image" + open-pull-requests-limit: 10 + cooldown: + default-days: 7 + semver-major-days: 30 + groups: + golang-base: + patterns: ["*golang*"] + azurelinux-base: + patterns: ["*azurelinux*"] + windows-base: + patterns: ["*windows*", "*nanoserver*", "*servercore*"] + ubuntu-base: + patterns: ["*ubuntu*"] + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" schedule: interval: "daily" reviewers: @@ -50,40 +41,36 @@ updates: commit-message: prefix: "deps" labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 3 - # Docker base image tracking - Tools (weekly) - - package-ecosystem: "docker" - directory: "/hack/tools/kapinger" - schedule: - interval: "weekly" - reviewers: - - "microsoft/retina" - commit-message: - prefix: "deps" - labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 3 - - package-ecosystem: "docker" - directory: "/hack/tools/toolbox" + open-pull-requests-limit: 10 + cooldown: + default-days: 3 + semver-major-days: 14 + groups: + actions-patch: + update-types: ["patch"] + + # npm (Docusaurus site) + - package-ecosystem: "npm" + directory: "/site" schedule: interval: "weekly" reviewers: - "microsoft/retina" commit-message: prefix: "deps" - labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 3 - # GitHub Actions tracking - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - reviewers: - - "microsoft/retina" - commit-message: - prefix: "deps" - labels: ["area/infra", "area/dependencies"] - open-pull-requests-limit: 10 - # Go modules tracking + labels: ["area/docs", "area/dependencies"] + open-pull-requests-limit: 5 + cooldown: + default-days: 7 + semver-major-days: 30 + groups: + docusaurus: + patterns: + - "@docusaurus/*" + - "@mdx-js/*" + update-types: ["patch"] + + # Go modules - package-ecosystem: "gomod" directory: "/" schedule: @@ -93,6 +80,32 @@ updates: commit-message: prefix: "deps" labels: ["lang/go", "area/dependencies"] - ignore: - - dependency-name: "github.com/inspektor-gadget/inspektor-gadget" open-pull-requests-limit: 10 + cooldown: + default-days: 7 + semver-major-days: 30 + groups: + k8s: + patterns: + - "k8s.io/*" + - "sigs.k8s.io/*" + exclude-patterns: + - "sigs.k8s.io/cloud-provider-azure/*" + update-types: ["patch"] + cilium: + patterns: + - "github.com/cilium/*" + update-types: ["patch"] + aws-sdk: + patterns: + - "github.com/aws/aws-sdk-go-v2/*" + update-types: ["patch"] + azure-sdk: + patterns: + - "github.com/Azure/*" + - "sigs.k8s.io/cloud-provider-azure/*" + update-types: ["patch"] + otel: + patterns: + - "go.opentelemetry.io/*" + update-types: ["patch"] From 2986fa4cfc4dfc8094550d64e03ccaa04072ab2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 16:50:37 +0000 Subject: [PATCH 341/448] deps: bump oss/go/microsoft/golang from `eb3ce81` to `d904c53` in /operator (#2234) Bumps oss/go/microsoft/golang from `eb3ce81` to `d904c53`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index e734072aa5..b2d51ae359 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 9c7f0a9dee..5e34b267ae 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder # Build args ARG VERSION From e70122f32987623445eafdfb183376867b6adc94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:01:26 -0400 Subject: [PATCH 342/448] deps: bump oss/go/microsoft/golang from `d904c53` to `ee3b117` in /controller (#2242) Bumps oss/go/microsoft/golang from `d904c53` to `ee3b117`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-windowsservercore-ltsc2022&new-version=1.26.2-windowsservercore-ltsc2022)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index be763d4461..abc4173eb4 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 135e98ac86..584fa1f258 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 95b020223d..7249f7c3bb 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 028dcb15a2..e5f8252855 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:ebf83c70a353e25631b0d52fafa8f8e12c37b66dfba20641a58044d6df9059fb AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:6c1a19b81f62d49adffc69b41b6af5939e240f5797847697e12402b0b7aef127 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 90134d444e..e0e176548a 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:ebf83c70a353e25631b0d52fafa8f8e12c37b66dfba20641a58044d6df9059fb AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:6c1a19b81f62d49adffc69b41b6af5939e240f5797847697e12402b0b7aef127 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . From c05b2a23fda1f2f62d5072ce8393a2f69efc3d36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:54:33 -0400 Subject: [PATCH 343/448] deps: bump oss/go/microsoft/golang from `d904c53` to `ee3b117` in /test/image (#2243) Bumps oss/go/microsoft/golang from `d904c53` to `ee3b117`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 7bb08f4e5c..ec0912e989 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 1f5529af11955bd13d670c0f92f91d2dd75b64c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:47:06 -0400 Subject: [PATCH 344/448] deps: bump oss/go/microsoft/golang from `6c27ae4` to `c6bf341` in /hack/tools/toolbox (#2240) Bumps oss/go/microsoft/golang from `6c27ae4` to `c6bf341`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2&new-version=1.26.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/tools/toolbox/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 129719f4eb..f006a69e8a 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:6c27ae470941ef215b3eea86fcd6632a7ab975f391e5a75f546d3a76fd686705 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:c6bf34143196d35a93f081ab0597550851d5d1c20fa45b2cf48d7d6da587a92c AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . From 12d0ae7c6ee987a0c9c6e0601fa41643aeda59a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:15:22 +0000 Subject: [PATCH 345/448] deps: bump oss/go/microsoft/golang from `eb3ce81` to `d904c53` in /cli (#2233) Bumps oss/go/microsoft/golang from `eb3ce81` to `d904c53`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index df184ff3ee..b7b2247210 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:eb3ce814e96f3319f1b5985021021682b47975f6decfe00eaac84abff0ae25c9 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder ARG VERSION ARG APP_INSIGHTS_ID From 31900b0fa45905ecc1a678f827cee6f80d63ad8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:13:49 -0400 Subject: [PATCH 346/448] deps: bump oss/go/microsoft/golang from `d904c53` to `ee3b117` in /operator (#2247) Bumps oss/go/microsoft/golang from `d904c53` to `ee3b117`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index b2d51ae359..8bf5173672 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 5e34b267ae..5d1decafcb 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder # Build args ARG VERSION From e7f7931320e44504d3c7de8be5dfa8ef11cb5c7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:05:26 -0400 Subject: [PATCH 347/448] deps: bump oss/go/microsoft/golang from `d904c53` to `ee3b117` in /cli (#2248) Bumps oss/go/microsoft/golang from `d904c53` to `ee3b117`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index b7b2247210..3dd13e838f 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:d904c53bb6a3a572482ff630fbd90cf487d5b8b3c4c8fe0e1d0b59d5d251bc8c AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder ARG VERSION ARG APP_INSIGHTS_ID From 2f4fb4541dbdd86ef88ba62d96e394b153f67278 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:01:24 -0400 Subject: [PATCH 348/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader from 0.13.0 to 0.14.0 (#2246) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.13.0 to 0.14.0.
Commits
  • c1f313b build(deps): bump the all group in /pkg/azclient with 4 updates (#9823)
  • 69efd5d build(deps): bump github/codeql-action in the all group (#9826)
  • fd46502 helm: back-compat MCR defaults (#9821)
  • bc2f0f0 Merge pull request #9798 from landreasyan/early-vmss-detach-exist
  • a334b30 Merge pull request #9816 from nilo19/test/fix-calico
  • 62d72ac test: Update calico settings in dualstack template based on capz example
  • deee5e9 Merge pull request #9815 from nilo19/test/tigera
  • 4e7f40d test: Use quay.io image registry for tigera/operator
  • 4eb0f5b feat(helm): use Dalec for >= v1.32.11 (#9792)
  • 19a3ebb build(deps): bump the all group in /kubetest2-aks with 2 updates (#9781)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader&package-manager=go_modules&previous-version=0.13.0&new-version=0.14.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4d43b91c59..d7682a105d 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( go.uber.org/zap v1.27.1 k8s.io/client-go v0.35.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0 - sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 + sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 ) retract ( diff --git a/go.sum b/go.sum index a658f86c05..2345626f21 100644 --- a/go.sum +++ b/go.sum @@ -2035,8 +2035,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUo sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0 h1:RuMG+Vi+tss3+wkWdZijb9Oh06bR1LYpYGx7bCsMays= sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0/go.mod h1:3exQL0c2uraRFH64nTYNvTYAeEwyglaj3X/BIvxaDU4= -sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0 h1:lJR9oMwgaUvKqWp+Pt2F/dpqEpiU8PpxELV5cA65rGE= -sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.13.0/go.mod h1:xSnyMWmeA+LeCdpM15e56eZZOVjd4SXUVvFrfSQISdI= +sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 h1:yjbZWgLUgTnLCGxM8I88l88WgvLRIOcOmAEbacFVLnU= +sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0/go.mod h1:6NYpRYlC7AyQaDtOQsF62plL1gDQqJwgQUwTdjp8qlU= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250517180713-32e5e9e948a5 h1:eOG9vIdpeOc/NI5RStnrYrEL4Crf66SHtfpVXwvRaNc= From c0a6526adda81e7a5b2bcea4575f50d36202ca44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:47:43 -0400 Subject: [PATCH 349/448] deps: bump oss/go/microsoft/golang from `6c27ae4` to `c6bf341` in /hack/tools/kapinger (#2241) Bumps oss/go/microsoft/golang from `6c27ae4` to `c6bf341`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2&new-version=1.26.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/tools/kapinger/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 46fd7258fa..79a32f584e 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:6c27ae470941ef215b3eea86fcd6632a7ab975f391e5a75f546d3a76fd686705 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:c6bf34143196d35a93f081ab0597550851d5d1c20fa45b2cf48d7d6da587a92c AS builder WORKDIR /build ADD . . @@ -17,7 +17,7 @@ CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:6c27ae470941ef215b3eea86fcd6632a7ab975f391e5a75f546d3a76fd686705 AS windows-builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:c6bf34143196d35a93f081ab0597550851d5d1c20fa45b2cf48d7d6da587a92c AS windows-builder WORKDIR /build ADD . . From d30dc304c59bccec5f09acf7f82a5aeb278cd2ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:43:53 -0400 Subject: [PATCH 350/448] deps: bump goreleaser/goreleaser-action from 7.1.0 to 7.2.1 (#2252) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 7.1.0 to 7.2.1.
Commits
  • 1a80836 ci(nightly): pass GITHUB_TOKEN to nightly integration job
  • a71152e refactor: drop legacy 'nightly' tag fallback
  • 4c6ab56 feat: resolve nightly to latest vX.Y.Z-<sha>-nightly release (#558)
  • 4f96abf feat: add version-file input (#556)
  • 15fa2a9 test: cover install across release eras (#555)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=goreleaser/goreleaser-action&package-manager=github_actions&previous-version=7.1.0&new-version=7.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 623a97951e..c758d38e3c 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -31,7 +31,7 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser build - uses: goreleaser/goreleaser-action@e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c # v7.1.0 + uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1 env: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent with: @@ -55,7 +55,7 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser release - uses: goreleaser/goreleaser-action@e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c # v7.1.0 + uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1 with: distribution: goreleaser version: latest From 6e853b823cb8fefa15682954f09d383d68175572 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:01:02 -0400 Subject: [PATCH 351/448] deps: bump github.com/onsi/ginkgo/v2 from 2.28.1 to 2.28.2 (#2253) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.28.1 to 2.28.2.
Changelog

Sourced from github.com/onsi/ginkgo/v2's changelog.

2.28.2

  • Add ArtifactDir() to support Go 1.26 testing.TB interface [f3a36b6]
  • Implement shell completion [94151c8]
  • Add asan CLI option mirroring msan implementation [4d21dbb]
  • Bump uri from 1.0.3 to 1.0.4 in /docs (#1630) [c102161]
  • fix aspect ratio [9619647]
  • update logos [5779304]
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/onsi/ginkgo/v2&package-manager=go_modules&previous-version=2.28.1&new-version=2.28.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d7682a105d..46e28818c4 100644 --- a/go.mod +++ b/go.mod @@ -244,7 +244,7 @@ require ( github.com/mdlayher/netlink v1.11.1 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c - github.com/onsi/ginkgo/v2 v2.28.1 + github.com/onsi/ginkgo/v2 v2.28.2 github.com/onsi/gomega v1.39.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 diff --git a/go.sum b/go.sum index 2345626f21..b95730f766 100644 --- a/go.sum +++ b/go.sum @@ -1262,8 +1262,8 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= -github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= +github.com/onsi/ginkgo/v2 v2.28.2 h1:DTrMfpqxiNUyQ3Y0zhn1n3cOO2euFgQPYIpkWwxVFps= +github.com/onsi/ginkgo/v2 v2.28.2/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= From 1700432a636b8091f67f146f550ec7511534e502 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:32:35 +0000 Subject: [PATCH 352/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.18.0 to 0.19.0 (#2258) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.18.0 to 0.19.0.
Commits
  • cc86551 build(deps): bump github.com/onsi/ginkgo/v2 (#10230)
  • daca812 build(deps): bump aquasecurity/trivy-action in the all group (#10232)
  • 203e986 build(deps): bump the all group in /kubetest2-aks with 2 updates (#10229)
  • 323d9cc Merge pull request #10227 from andyzhangx/add-smboauth-equal-check
  • 7ee5aa3 test: assert full accountWithLocation fields, not just name
  • b615073 test: improve SmbOAuth edge cases with HTTPS check and multi-account assertion
  • 6389d5d fix: correct goimports alignment for ResourceGroup field in test cases
  • ab75e28 fix: set EnableHTTPSTrafficOnly in SmbOAuth test case to pass HTTPS check
  • b948011 test: add missing isSmbOAuthEnabledEqual test cases
  • 71b5409 feat: add isSmbOAuthEnabledEqual check to storage account matching
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.18.0&new-version=0.19.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 46e28818c4..918b4b0c41 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.27.1 k8s.io/client-go v0.35.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 ) diff --git a/go.sum b/go.sum index b95730f766..799caeccd4 100644 --- a/go.sum +++ b/go.sum @@ -2033,8 +2033,8 @@ oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0 h1:RuMG+Vi+tss3+wkWdZijb9Oh06bR1LYpYGx7bCsMays= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.18.0/go.mod h1:3exQL0c2uraRFH64nTYNvTYAeEwyglaj3X/BIvxaDU4= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0 h1:dh6aoXX1aofigfsRDZPECa4rat1NBKcE6ZQlhx2F2hY= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0/go.mod h1:qIX6mr9uEnUlC+3BQCjFBR9c4Qj+5mN0hrNZIYdMFWE= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 h1:yjbZWgLUgTnLCGxM8I88l88WgvLRIOcOmAEbacFVLnU= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0/go.mod h1:6NYpRYlC7AyQaDtOQsF62plL1gDQqJwgQUwTdjp8qlU= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= From e32cd0be47f85a88c9309e52c23e8546a79c1b1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:41:36 -0400 Subject: [PATCH 353/448] deps: bump oss/go/microsoft/golang from `ee3b117` to `0feda24` in /operator (#2257) Bumps oss/go/microsoft/golang from `ee3b117` to `0feda24`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index 8bf5173672..565f8063e6 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 5d1decafcb..0fd18123a8 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder # Build args ARG VERSION From 78f384ceca157354dd7e6e506039ee80c8538d49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:49:05 -0400 Subject: [PATCH 354/448] deps: bump oss/go/microsoft/golang from `ee3b117` to `0feda24` in /controller (#2254) Bumps oss/go/microsoft/golang from `ee3b117` to `0feda24`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-windowsservercore-ltsc2022&new-version=1.26.2-windowsservercore-ltsc2022)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index abc4173eb4..7f2cba43b2 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 584fa1f258..e34bb651a2 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 7249f7c3bb..c75ff41554 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index e5f8252855..3f48e86a69 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:6c1a19b81f62d49adffc69b41b6af5939e240f5797847697e12402b0b7aef127 AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:17b43d646f113abf7e2550fe5fb3b79a29083f36d38171fbfa265fedbb452416 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index e0e176548a..d39b99b8ce 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:6c1a19b81f62d49adffc69b41b6af5939e240f5797847697e12402b0b7aef127 AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:17b43d646f113abf7e2550fe5fb3b79a29083f36d38171fbfa265fedbb452416 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . From 81312428ed02f0faa3947d9fd36be470ba24514a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 18:53:13 -0400 Subject: [PATCH 355/448] deps: bump oss/go/microsoft/golang from `ee3b117` to `0feda24` in /cli (#2255) Bumps oss/go/microsoft/golang from `ee3b117` to `0feda24`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 3dd13e838f..786496db1a 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder ARG VERSION ARG APP_INSIGHTS_ID From b0a971ed66b31aaf80c7f848b4a2769c547ebc1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 08:55:57 -0400 Subject: [PATCH 356/448] deps: bump oss/go/microsoft/golang from `ee3b117` to `0feda24` in /test/image (#2256) Bumps oss/go/microsoft/golang from `ee3b117` to `0feda24`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/Dockerfile b/test/image/Dockerfile index ec0912e989..1b78b4184d 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:ee3b11755cb3401848dc3140bbaae8da81dce6f7c7569857b2f45f040ae8868b AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From f443042e37efcf10f9724d997467a0be3b1eb0f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 11:22:19 -0400 Subject: [PATCH 357/448] deps: bump go.uber.org/zap from 1.27.1 to 1.28.0 (#2259) Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.27.1 to 1.28.0.
Release notes

Sourced from go.uber.org/zap's releases.

v1.28.0

Enhancements:

  • #1534[]: Add zapcore.CheckPreWriteHook and CheckedEntry.Before method for transforming entries before they are written to any Cores.

#1534: uber-go/zap#1534

Changelog

Sourced from go.uber.org/zap's changelog.

1.28.0 (27 Apr 2026)

Enhancements:

  • #1534[]: Add zapcore.CheckPreWriteHook and CheckedEntry.Before method for transforming entries before they are written to any Cores.
Commits
  • 5b81b37 release v1.28.0 (#1547)
  • 0ab0d5a zapcore: Add PreWriteHook for transforming entries before write (#1534)
  • d278c59 [chore] CI: test on Go 1.26 (#1535)
  • 16fb16b chore(dep): replace archived gopkg.in/yaml.v3 with officially maintained go.y...
  • See full diff in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 918b4b0c41..d71aada9ae 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.23.2 github.com/spf13/cobra v1.10.2 - go.uber.org/zap v1.27.1 + go.uber.org/zap v1.28.0 k8s.io/client-go v0.35.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 diff --git a/go.sum b/go.sum index 799caeccd4..87616b151e 100644 --- a/go.sum +++ b/go.sum @@ -1696,8 +1696,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= -go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= +go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U= go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= From ad45b106d11f53db1d66b30504092d27333191b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:21:31 -0400 Subject: [PATCH 358/448] deps: bump github.com/onsi/ginkgo/v2 from 2.28.2 to 2.28.3 (#2261) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.28.2 to 2.28.3.
Release notes

Sourced from github.com/onsi/ginkgo/v2's releases.

v2.28.3

2.28.3

Maintenance

Bump all dependencies

Changelog

Sourced from github.com/onsi/ginkgo/v2's changelog.

2.28.3

Maintenance

Bump all dependencies

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/onsi/ginkgo/v2&package-manager=go_modules&previous-version=2.28.2&new-version=2.28.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index d71aada9ae..ee7a5301fc 100644 --- a/go.mod +++ b/go.mod @@ -244,8 +244,8 @@ require ( github.com/mdlayher/netlink v1.11.1 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c - github.com/onsi/ginkgo/v2 v2.28.2 - github.com/onsi/gomega v1.39.1 + github.com/onsi/ginkgo/v2 v2.28.3 + github.com/onsi/gomega v1.40.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.67.5 @@ -474,7 +474,7 @@ require ( github.com/google/go-github/v62 v62.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/ko v0.15.4 // indirect - github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect + github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect github.com/google/rpmpack v0.7.1 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect diff --git a/go.sum b/go.sum index 87616b151e..6105ad9301 100644 --- a/go.sum +++ b/go.sum @@ -836,8 +836,8 @@ github.com/google/ko v0.15.4 h1:0blRbIdPmSy6v4LvedGxbI/8krdJYQgbSih3v6Y8V1c= github.com/google/ko v0.15.4/go.mod h1:ZkcmfV91Xt6ZzOBHc/cXXGYnqWdNWDVy/gHoUU9sjag= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= -github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= -github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= +github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg= +github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.2 h1:qKZs+tfn+arruZZhQ7TKC/ergJunuJicWS6gLDt/dGw= github.com/google/renameio/v2 v2.0.2/go.mod h1:OX+G6WHHpHq3NVj7cAOleLOwJfcQ1s3uUJQCrr78SWo= @@ -1262,13 +1262,13 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.28.2 h1:DTrMfpqxiNUyQ3Y0zhn1n3cOO2euFgQPYIpkWwxVFps= -github.com/onsi/ginkgo/v2 v2.28.2/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= +github.com/onsi/ginkgo/v2 v2.28.3 h1:4JvMdwtFU0imd8fHx25OJXoDMRexnf8v5NHKYSTTji4= +github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= -github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc= +github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= 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= From 7b57f0b082fada977177c8a852fc94e915ada984 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 19:30:25 -0400 Subject: [PATCH 359/448] deps: bump oss/go/microsoft/golang from `0feda24` to `637bcd5` in /controller (#2266) Bumps oss/go/microsoft/golang from `0feda24` to `637bcd5`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-windowsservercore-ltsc2022&new-version=1.26.2-windowsservercore-ltsc2022)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 7f2cba43b2..144df793ee 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index e34bb651a2..12fa6c7d2f 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index c75ff41554..df07a623ae 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 3f48e86a69..7d57e10505 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:17b43d646f113abf7e2550fe5fb3b79a29083f36d38171fbfa265fedbb452416 AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:4516f9a8c99ac6f4cc0b80ce397a67671d804ed42639f3e13790ef01b33cf67c AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index d39b99b8ce..6d5c10a041 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:17b43d646f113abf7e2550fe5fb3b79a29083f36d38171fbfa265fedbb452416 AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:4516f9a8c99ac6f4cc0b80ce397a67671d804ed42639f3e13790ef01b33cf67c AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . From 40c8d1634278134710e91d73eecdb392a0b2cc53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 21:40:53 -0400 Subject: [PATCH 360/448] deps: bump oss/go/microsoft/golang from `0feda24` to `637bcd5` in /operator (#2263) Bumps oss/go/microsoft/golang from `0feda24` to `637bcd5`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index 565f8063e6..e6f52866ec 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 0fd18123a8..00261ee51a 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder # Build args ARG VERSION From 73a80944923cd550ca4265e2635f66fd79ae3006 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:47:38 -0400 Subject: [PATCH 361/448] deps: bump oss/go/microsoft/golang from `0feda24` to `637bcd5` in /cli (#2265) Bumps oss/go/microsoft/golang from `0feda24` to `637bcd5`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 786496db1a..29a43b5c45 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder ARG VERSION ARG APP_INSIGHTS_ID From 0c0fd6b19fb1a4a9996f012e99be111a08e474d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:52:04 -0400 Subject: [PATCH 362/448] deps: bump github.com/aws/aws-sdk-go-v2 from 1.41.6 to 1.41.7 (#2271) Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.41.6 to 1.41.7.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2&package-manager=go_modules&previous-version=1.41.6&new-version=1.41.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ee7a5301fc..c1db6d96ed 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect - github.com/aws/smithy-go v1.25.0 // indirect + github.com/aws/smithy-go v1.25.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -224,7 +224,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 github.com/Microsoft/hcsshim v0.14.1 - github.com/aws/aws-sdk-go-v2 v1.41.6 + github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.16 github.com/aws/aws-sdk-go-v2/credentials v1.19.15 github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 diff --git a/go.sum b/go.sum index 6105ad9301..a5d79f544a 100644 --- a/go.sum +++ b/go.sum @@ -257,8 +257,8 @@ github.com/atc0005/go-teams-notify/v2 v2.10.0 h1:eQvRIkyESQgBvlUdQ/iPol/lj3QcRyr github.com/atc0005/go-teams-notify/v2 v2.10.0/go.mod h1:SIeE1UfCcVRYMqP5b+r1ZteHyA/2UAjzWF5COnZ8q0w= github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= -github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= -github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= +github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= +github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM= @@ -299,8 +299,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 h1:oK/njaL8GtyEihkWMD4k3Vg github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20/go.mod h1:JHs8/y1f3zY7U5WcuzoJ/yAYGYtNIVPKLIbp61euvmg= github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 h1:ks8KBcZPh3PYISr5dAiXCM5/Thcuxk8l+PG4+A0exds= github.com/aws/aws-sdk-go-v2/service/sts v1.42.0/go.mod h1:pFw33T0WLvXU3rw1WBkpMlkgIn54eCB5FYLhjDc9Foo= -github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U= -github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= +github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 h1:6lMw4/QGLFPvbKQ0eri/9Oh3YX5Nm6BPrUlZR8yuJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1/go.mod h1:EVJOSYOVeoD3VFFZ/dWCAzWJp5wZr9lTOCjW8ejAmO0= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From 856d89eda4b47ab8bfa1b9fe36172f01c2d73797 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 12:33:09 -0400 Subject: [PATCH 363/448] deps: bump oss/go/microsoft/golang from `0feda24` to `637bcd5` in /test/image (#2264) Bumps oss/go/microsoft/golang from `0feda24` to `637bcd5`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 1b78b4184d..979b0b0516 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:0feda2470445a2193dfc48a04df6c682987a65431b43523f77fbdd3c1648e24e AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 122720841999370346c100ac4efd112ac074ca44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 18:25:40 -0400 Subject: [PATCH 364/448] deps: bump github/codeql-action from 4.35.2 to 4.35.3 (#2276) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.2 to 4.35.3.
Release notes

Sourced from github/codeql-action's releases.

v4.35.3

  • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. #3837
  • Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. #3850
  • Best-effort connection tests for private registries now use GET requests instead of HEAD for better compatibility with various registry implementations. For NuGet feeds, the test is now always performed against the service index. #3853
  • Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. #3852
  • Update default CodeQL bundle version to 2.25.3. #3865
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.35.3 - 01 May 2026

  • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. #3837
  • Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. #3850
  • Best-effort connection tests for private registries now use GET requests instead of HEAD for better compatibility with various registry implementations. For NuGet feeds, the test is now always performed against the service index. #3853
  • Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. #3852
  • Update default CodeQL bundle version to 2.25.3. #3865

4.35.2 - 15 Apr 2026

  • The undocumented TRAP cache cleanup feature that could be enabled using the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the trap-caching: false input to the init Action. #3795
  • The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. #3789
  • Python analysis on GHES no longer extracts the standard library, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. #3794
  • Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. #3807
  • Update default CodeQL bundle version to 2.25.2. #3823

4.35.1 - 27 Mar 2026

4.35.0 - 27 Mar 2026

4.34.1 - 20 Mar 2026

  • Downgrade default CodeQL bundle version to 2.24.3 due to issues with a small percentage of Actions and JavaScript analyses. #3762

4.34.0 - 20 Mar 2026

  • Added an experimental change which disables TRAP caching when improved incremental analysis is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. #3569
  • We are rolling out improved incremental analysis to C/C++ analyses that use build mode none. We expect this rollout to be complete by the end of April 2026. #3584
  • Update default CodeQL bundle version to 2.25.0. #3585

4.33.0 - 16 Mar 2026

  • Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. #3562

    To opt out of this change:

    • Repositories owned by an organization: Create a custom repository property with the name github-codeql-file-coverage-on-prs and the type "True/false", then set this property to true in the repository's settings. For more information, see Managing custom properties for repositories in your organization. Alternatively, if you are using an advanced setup workflow, you can set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using default setup: Switch to an advanced setup workflow and set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.

... (truncated)

Commits
  • e46ed2c Merge pull request #3867 from github/update-v4.35.3-8c6e48dbe
  • b73d1d1 Add changelog entry for #3853
  • 24e0bb0 Reorder changelog entries
  • ec298da Update changelog for v4.35.3
  • 8c6e48d Merge pull request #3865 from github/update-bundle/codeql-bundle-v2.25.3
  • 7190983 Add changelog note
  • 2bb2095 Update default bundle to codeql-bundle-v2.25.3
  • 7851e55 Merge pull request #3850 from github/mbg/private-registry/cloudsmith-gcp
  • 262a15f Add generic non-printable chars test for OIDC configs
  • a6109b1 Merge pull request #3853 from github/mbg/start-proxy/improved-checks
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.35.2&new-version=4.35.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 24c96172c1..35204b93d1 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/autobuild@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 6aea486a5f..b22761c884 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 with: sarif_file: "trivy-results.sarif" From 58bac2fcff5cedc7fa81f0e703c9c7ca90c4507c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 16:42:15 -0400 Subject: [PATCH 365/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.100.0 to 1.100.1 (#2269) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.100.0 to 1.100.1.
Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index c1db6d96ed..74d6a76dfd 100644 --- a/go.mod +++ b/go.mod @@ -44,15 +44,15 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect @@ -227,7 +227,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.16 github.com/aws/aws-sdk-go-v2/credentials v1.19.15 - github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 github.com/cilium/ebpf v0.21.0 diff --git a/go.sum b/go.sum index a5d79f544a..fb679beec7 100644 --- a/go.sum +++ b/go.sum @@ -259,8 +259,8 @@ github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 h1:gx1AwW1Iyk9Z9dD9F4akX5gnN3QZwUB20GGKH/I+Rho= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10/go.mod h1:qqY157uZoqm5OXq/amuaBJyC9hgBCBQnsaWnPe905GY= github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM= github.com/aws/aws-sdk-go-v2/config v1.32.16/go.mod h1:duCCnJEFqpt2RC6no1iK6q+8HpwOAkiUua0pY507dQc= github.com/aws/aws-sdk-go-v2/credentials v1.19.15 h1:fyvgWTszojq8hEnMi8PPBTvZdTtEVmAVyo+NFLHBhH4= @@ -269,28 +269,28 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 h1:IOGsJ1xVWhsi+ZO7/NW8Ou github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22/go.mod h1:b+hYdbU+jGKfXE8kKM6g1+h+L/Go3vMvzlxBsiuGsxg= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 h1:1hWFp+52Vq8Fevy/KUhbW/1MEApMz7uitCF/PQXRJpk= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1/go.mod h1:sIec8j802/rCkCKgZV678HFR0s7lhQUYXT77tIvlaa4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 h1:Bwzh202Aq7/MYnAjXA9VawCf6u+hjwMdoYmZ4HYsdf8= github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1/go.mod h1:xZzWl9AXYa6zsLLH41HBFW8KRKJRIzlGmvSM0mVMIX4= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 h1:XJ/AEFYj9VFPJdF+VFi4SUPEDfz1akHwxxm07JfZJcs= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2/go.mod h1:JUBHdhvKbbKmhaHjLsKJAWnQL80T6nURmhB/LEprV+4= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 h1:ieLCO1JxUWuxTZ1cRd0GAaeX7O6cIxnwk7tc1LsQhC4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15/go.mod h1:e3IzZvQ3kAWNykvE0Tr0RDZCMFInMvhku3qNpcIQXhM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 h1:03xatSQO4+AM1lTAbnRg5OK528EUg744nW7F73U8DKw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23/go.mod h1:M8l3mwgx5ToK7wot2sBBce/ojzgnPzZXUV445gTSyE8= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 h1:mxuT1xE+dI54NW3RkNjP8DUT5HXqbkiAFvfdyDFwE5c= +github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 h1:a1Fq/KXn75wSzoJaPQTgZO0wHGqE9mjFnylnqEPTchA= github.com/aws/aws-sdk-go-v2/service/signin v1.0.10/go.mod h1:p6+MXNxW7IA6dMgHfTAzljuwSKD0NCm/4lbS4t6+7vI= github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 h1:x6bKbmDhsgSZwv6q19wY/u3rLk/3FGjJWyqKcIRufpE= From f52e0756abde52c3ccbcc9b3156e456ffa080aa4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 18:22:09 -0400 Subject: [PATCH 366/448] deps: bump github.com/aws/aws-sdk-go-v2/config from 1.32.16 to 1.32.17 (#2275) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.32.16 to 1.32.17.
Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 74d6a76dfd..3fa80483ba 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect @@ -53,9 +53,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 // indirect github.com/aws/smithy-go v1.25.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 @@ -225,8 +225,8 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 github.com/Microsoft/hcsshim v0.14.1 github.com/aws/aws-sdk-go-v2 v1.41.7 - github.com/aws/aws-sdk-go-v2/config v1.32.16 - github.com/aws/aws-sdk-go-v2/credentials v1.19.15 + github.com/aws/aws-sdk-go-v2/config v1.32.17 + github.com/aws/aws-sdk-go-v2/credentials v1.19.16 github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 @@ -345,7 +345,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ecr v1.45.1 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.2 // indirect github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect diff --git a/go.sum b/go.sum index fb679beec7..3b410ed705 100644 --- a/go.sum +++ b/go.sum @@ -261,12 +261,12 @@ github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6t github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 h1:gx1AwW1Iyk9Z9dD9F4akX5gnN3QZwUB20GGKH/I+Rho= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10/go.mod h1:qqY157uZoqm5OXq/amuaBJyC9hgBCBQnsaWnPe905GY= -github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM= -github.com/aws/aws-sdk-go-v2/config v1.32.16/go.mod h1:duCCnJEFqpt2RC6no1iK6q+8HpwOAkiUua0pY507dQc= -github.com/aws/aws-sdk-go-v2/credentials v1.19.15 h1:fyvgWTszojq8hEnMi8PPBTvZdTtEVmAVyo+NFLHBhH4= -github.com/aws/aws-sdk-go-v2/credentials v1.19.15/go.mod h1:gJiYyMOjNg8OEdRWOf3CrFQxM2a98qmrtjx1zuiQfB8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 h1:IOGsJ1xVWhsi+ZO7/NW8OuZZBtMJLZbk4P5HDjJO0jQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22/go.mod h1:b+hYdbU+jGKfXE8kKM6g1+h+L/Go3vMvzlxBsiuGsxg= +github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU= +github.com/aws/aws-sdk-go-v2/config v1.32.17/go.mod h1:OXqUMzgXytfoF9JaKkhrOYsyh72t9G+MJH8mMRaexOE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16 h1:r3RJBuU7X9ibt8RHbMjWE6y60QbKBiII6wSrXnapxSU= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16/go.mod h1:6cx7zqDENJDbBIIWX6P8s0h6hqHC8Avbjh9Dseo27ug= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1 h1:1hWFp+52Vq8Fevy/KUhbW/1MEApMz7uitCF/PQXRJpk= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.21.1/go.mod h1:sIec8j802/rCkCKgZV678HFR0s7lhQUYXT77tIvlaa4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= @@ -291,14 +291,14 @@ github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 h1:mxuT1xE+dI54NW3RkNjP8DUT5HXqbkiAFvfdyDFwE5c= github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 h1:a1Fq/KXn75wSzoJaPQTgZO0wHGqE9mjFnylnqEPTchA= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.10/go.mod h1:p6+MXNxW7IA6dMgHfTAzljuwSKD0NCm/4lbS4t6+7vI= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 h1:x6bKbmDhsgSZwv6q19wY/u3rLk/3FGjJWyqKcIRufpE= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.16/go.mod h1:CudnEVKRtLn0+3uMV0yEXZ+YZOKnAtUJ5DmDhilVnIw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 h1:oK/njaL8GtyEihkWMD4k3VgHCT64RQKkZwh0DG5j8ak= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20/go.mod h1:JHs8/y1f3zY7U5WcuzoJ/yAYGYtNIVPKLIbp61euvmg= -github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 h1:ks8KBcZPh3PYISr5dAiXCM5/Thcuxk8l+PG4+A0exds= -github.com/aws/aws-sdk-go-v2/service/sts v1.42.0/go.mod h1:pFw33T0WLvXU3rw1WBkpMlkgIn54eCB5FYLhjDc9Foo= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29h8BvsCoHQEQ6ST9X8w7w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.10.1 h1:6lMw4/QGLFPvbKQ0eri/9Oh3YX5Nm6BPrUlZR8yuJHg= From 64db57625e68317e48c1ae0b377a74ce181395d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 19:47:40 -0400 Subject: [PATCH 367/448] deps: bump oss/go/microsoft/golang from `c6bf341` to `61e6078` in /hack/tools/toolbox (#2273) Bumps oss/go/microsoft/golang from `c6bf341` to `61e6078`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2&new-version=1.26.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/tools/toolbox/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index f006a69e8a..ae7e35b662 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:c6bf34143196d35a93f081ab0597550851d5d1c20fa45b2cf48d7d6da587a92c AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:61e607875d60ae21a7a4a49110fe7098355473fbc74ab13091e3c1160cc92f18 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . From 05d80316988212a7bd9ba1222c93ab5015eb6421 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 23:11:50 -0400 Subject: [PATCH 368/448] deps: bump oss/go/microsoft/golang from `c6bf341` to `61e6078` in /hack/tools/kapinger (#2272) Bumps oss/go/microsoft/golang from `c6bf341` to `61e6078`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2&new-version=1.26.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/tools/kapinger/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 79a32f584e..738c66f92c 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:c6bf34143196d35a93f081ab0597550851d5d1c20fa45b2cf48d7d6da587a92c AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:61e607875d60ae21a7a4a49110fe7098355473fbc74ab13091e3c1160cc92f18 AS builder WORKDIR /build ADD . . @@ -17,7 +17,7 @@ CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:c6bf34143196d35a93f081ab0597550851d5d1c20fa45b2cf48d7d6da587a92c AS windows-builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:61e607875d60ae21a7a4a49110fe7098355473fbc74ab13091e3c1160cc92f18 AS windows-builder WORKDIR /build ADD . . From 4cda9ae2486f6323eb6d3770ace988d4d79a99cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 19:44:24 -0400 Subject: [PATCH 369/448] deps: bump google.golang.org/grpc from 1.80.0 to 1.81.0 (#2281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.80.0 to 1.81.0.
Release notes

Sourced from google.golang.org/grpc's releases.

Release 1.81.0

Behavior Changes

  • balancer/rls: Switch gauge metrics to asynchronous emission (once per collection cycle) to reduce telemetry noise and align with other gRPC language implementations. (#8808)

Dependencies

  • Minimum supported Go version is now 1.25. (#8969)

Bug Fixes

  • xds: Use the leaf cluster's security config for the TLS handshake instead of the aggregate cluster's config. (#8956)
  • transport: Send a RST_STREAM when receiving an END_STREAM when the stream is not already half-closed. (#8832)
  • xds: Fix ADS resource name validation to prevent a panic. (#8970)

New Features

  • grpc/stats: Add support for custom labels in per-call metrics (gRFC A108). (#9008)
  • xds: Add support for Server Name Indication (SNI) and SAN validation (gRFC A101). Disabled by default. To enable, set GRPC_EXPERIMENTAL_XDS_SNI=true environment variable. (#9016)
  • xds: Add support to control which fields get propagated from ORCA backend metric reports to LRS load reports (gRFC A85). Disabled by default. To enable, set GRPC_EXPERIMENTAL_XDS_ORCA_LRS_PROPAGATION=true. (#9005)
  • xds: Add metrics to track xDS client connectivity and cached resource state (gRFC A78). (#8807)
  • stats/otel: Enhance grpc.subchannel.disconnections metric by adding disconnection reason to the grpc.disconnect_error label (gRFC A94). This provides granular insights into why subchannels are closing. (#8973)
  • mem: Add mem.Buffer.Slice() API to slice the buffer like a slice. (#8977)

Performance Improvements

  • alts: Pool read buffers to lower memory utilization when sockets are unreadable. (#8964)
  • transport: Pool HTTP/2 framer read buffers to reduce idle memory consumption. Currently limited to Linux for ALTS and non-encrypted transports (TCP, Unix). To disable, set GRPC_GO_EXPERIMENTAL_HTTP_FRAMER_READ_BUFFER_POOLING=false and report any issues. (#9032)
Commits
  • cb18228 Change version to 1.81.0 (#9062)
  • 96748f9 Cherry-pick #9105 to 1.81.x (#9106)
  • 9183222 Cherry pick #9055, #9032 to v1.81.x (#9095)
  • 5cba6da Revert "deps: update dependencies for all modules (#9065)" (#9067)
  • af8a936 deps: update dependencies for all modules (#9065)
  • cdc60df transport: optimize heap allocations in ready reader and update syscall conne...
  • 208d053 xds/resolver: pass complete XDSConfig in RPC context for HTTP filters (gRFC A...
  • 50fe1cc test: Fix flaky test TestServerStreaming_ClientCallRecvMsgTwice in `end2end...
  • d574bad build(deps): bump go.opentelemetry.io/otel/sdk from 1.42.0 to 1.43.0 (#9050)
  • b8bf4d0 build(deps): bump go.opentelemetry.io/otel/sdk from 1.42.0 to 1.43.0 in /inte...
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.80.0&new-version=1.81.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 3fa80483ba..8a5ad034f7 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/cilium/dns v1.1.51-0.20240603182237-af788769786a // indirect github.com/cilium/lumberjack/v2 v2.4.1 // indirect github.com/cilium/stream v0.0.1 // indirect - github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect github.com/containerd/containerd v1.7.30 // indirect github.com/containerd/errdefs v1.0.0 // indirect @@ -258,7 +258,7 @@ require ( go.uber.org/mock v0.6.0 go.uber.org/zap/exp v0.3.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f - google.golang.org/grpc v1.80.0 + google.golang.org/grpc v1.81.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 @@ -417,7 +417,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect @@ -651,7 +651,7 @@ require ( go.augendre.info/arangolint v0.4.0 // indirect go.augendre.info/fatcontext v0.9.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.42.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 // indirect diff --git a/go.sum b/go.sum index 3b410ed705..2308275afb 100644 --- a/go.sum +++ b/go.sum @@ -434,8 +434,8 @@ github.com/cloudflare/cfssl v1.6.5/go.mod h1:Bk1si7sq8h2+yVEDrFJiz3d7Aw+pfjjJSZV github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= @@ -547,8 +547,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= -github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= -github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -1628,8 +1628,8 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0 h1:x7sPooQCwSg27SjtQee8GyIIRTQcF4s7eSkac6F2+VA= go.opentelemetry.io/contrib/bridges/prometheus v0.60.0/go.mod h1:4K5UXgiHxV484efGs42ejD7E2J/sIlepYgdGoPXe7hE= -go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= -go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= +go.opentelemetry.io/contrib/detectors/gcp v1.42.0 h1:kpt2PEJuOuqYkPcktfJqWWDjTEd/FNgrxcniL7kQrXQ= +go.opentelemetry.io/contrib/detectors/gcp v1.42.0/go.mod h1:W9zQ439utxymRrXsUOzZbFX4JhLxXU4+ZnCt8GG7yA8= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 h1:GuQXpvSXNjpswpweIem84U9BNauqHHi2w1GtNAalvpM= go.opentelemetry.io/contrib/exporters/autoexport v0.60.0/go.mod h1:CkmxekdHco4d7thFJNPQ7Mby4jMBgZUclnrxT4e+ryk= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= @@ -1935,8 +1935,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -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/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 136d0c78e8621f825046037da0275f4ed831b7a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 00:08:12 -0400 Subject: [PATCH 370/448] deps: bump oss/go/microsoft/golang from `637bcd5` to `257614f` in /controller (#2277) Bumps oss/go/microsoft/golang from `637bcd5` to `257614f`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-windowsservercore-ltsc2022&new-version=1.26.2-windowsservercore-ltsc2022)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 144df793ee..41f05b6929 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 12fa6c7d2f..91e26a1811 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index df07a623ae..51fcff84a0 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 7d57e10505..9fd3b71748 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:4516f9a8c99ac6f4cc0b80ce397a67671d804ed42639f3e13790ef01b33cf67c AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:7dc9ddecd32b6c338f2c9ac9b87f51eb7f1bc603af4fe389abefa0db310a8239 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 6d5c10a041..89faf7717e 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:4516f9a8c99ac6f4cc0b80ce397a67671d804ed42639f3e13790ef01b33cf67c AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:7dc9ddecd32b6c338f2c9ac9b87f51eb7f1bc603af4fe389abefa0db310a8239 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . From 0db55236c7827ef5f1964e7c137f3ccf0317fa9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 10:08:24 -0400 Subject: [PATCH 371/448] deps: bump oss/go/microsoft/golang from `637bcd5` to `257614f` in /operator (#2279) Bumps oss/go/microsoft/golang from `637bcd5` to `257614f`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index e6f52866ec..01fc869817 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 00261ee51a..2b77ab6f63 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder # Build args ARG VERSION From 0ee09e4c574e7ca21558ecfc951d42c023692674 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 15:22:00 -0400 Subject: [PATCH 372/448] deps: bump oss/go/microsoft/golang from `637bcd5` to `257614f` in /test/image (#2280) Bumps oss/go/microsoft/golang from `637bcd5` to `257614f`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 979b0b0516..f2676c5151 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 00db7a4e50c3c98ab82d41c409f0137e63a841c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 16:42:22 -0400 Subject: [PATCH 373/448] deps: bump oss/go/microsoft/golang from `637bcd5` to `257614f` in /cli (#2278) Bumps oss/go/microsoft/golang from `637bcd5` to `257614f`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.2-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 29a43b5c45..207ac25c29 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:637bcd53d7c139d2fa54d8d6e2bb3f9346b3ab1c9f03bb33ea56c3964d458f1b AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder ARG VERSION ARG APP_INSIGHTS_ID From 98f1bd2da6a19fbe482e1016235dbcc7c56413a7 Mon Sep 17 00:00:00 2001 From: Iti Agrawal Date: Fri, 8 May 2026 17:37:20 +0100 Subject: [PATCH 374/448] fix: remove credential-adjacent BlobUpload field from log lines (#2300) This pull request makes minor improvements to the logging in the `handleUpdate` method of the `CaptureReconciler` by updating log messages for clarity and removing redundant information. Logging improvements: * Updated error and info log messages to remove unnecessary details about the secret and to clarify when a capture is updated with a managed secret in `controller.go`.... Signed-off-by: Iti Agrawal Signed-off-by: Iti Agrawal --- pkg/controllers/operator/capture/controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controllers/operator/capture/controller.go b/pkg/controllers/operator/capture/controller.go index 121213d884..78d9a5d8bd 100644 --- a/pkg/controllers/operator/capture/controller.go +++ b/pkg/controllers/operator/capture/controller.go @@ -351,10 +351,10 @@ func (cr *CaptureReconciler) handleUpdate(ctx context.Context, capture *retinav1 // TODO(mainred): update Capture with container/blob info to simply the following blob download capture.Spec.OutputConfiguration.BlobUpload = to.Ptr(secret.Name) if err = cr.Client.Update(ctx, capture); err != nil { - cr.logger.Error("Failed to update capture with managed secret", zap.Error(err), zap.String("secret", secret.Name), zap.String("Capture", captureRef.String())) + cr.logger.Error("Failed to update capture with managed secret", zap.Error(err), zap.String("Capture", captureRef.String())) return ctrl.Result{}, fmt.Errorf("failed to update capture with managed secret: %w", err) } - cr.logger.Info("Use the existing secret", zap.Error(err), zap.String("Capture", captureRef.String()), zap.String("secret", *capture.Spec.OutputConfiguration.BlobUpload)) + cr.logger.Info("Capture updated with managed secret", zap.String("Capture", captureRef.String())) } } From 8808a37ce5e7b6755bacd983f4d5b0f0a115c9c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 20:02:48 -0400 Subject: [PATCH 375/448] chore(deps): bump the npm_and_yarn group across 1 directory with 3 updates (#2304) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the npm_and_yarn group with 3 updates in the /site directory: [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs), [fast-uri](https://github.com/fastify/fast-uri) and [postcss](https://github.com/postcss/postcss). Updates `@babel/plugin-transform-modules-systemjs` from 7.29.0 to 7.29.4
Release notes

Sourced from @​babel/plugin-transform-modules-systemjs's releases.

v7.29.4 (2026-05-05)

:bug: Bug Fix

  • babel-plugin-transform-modules-systemjs
    • #17974 [7.x backport]fix(systemjs): improve module string name support (@​JLHwung)

Committers: 1

v7.29.3 (2026-04-30)

:eyeglasses: Spec Compliance

:bug: Bug Fix

  • babel-helper-create-class-features-plugin, babel-plugin-proposal-decorators
    • #17931 fix(decorators): replace super within all removed static elements (@​JLHwung)
  • babel-register
  • babel-compat-data, babel-plugin-bugfix-safari-rest-destructuring-rhs-array, babel-preset-env

:nail_care: Polish

:memo: Documentation

:running_woman: Performance

  • babel-helper-import-to-platform-api, babel-plugin-proposal-import-wasm-source, babel-plugin-transform-json-modules

Committers: 4

v7.29.2 (2026-03-16)

:eyeglasses: Spec Compliance

  • babel-parser

:bug: Bug Fix

  • babel-helpers, babel-plugin-transform-async-generator-functions, babel-preset-env, babel-runtime-corejs3
  • babel-preset-env

... (truncated)

Commits

Updates `fast-uri` from 3.1.0 to 3.1.2
Release notes

Sourced from fast-uri's releases.

v3.1.2

⚠️ Security Release

What's Changed

Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.1...v3.1.2

v3.1.1

⚠️ Security Release

What's Changed

New Contributors

Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.0...v3.1.1

Commits
  • 919dd8e Bumped v3.1.2
  • c65ba57 fixup: linting
  • 6c86c17 Merge commit from fork
  • a95158a Handle malformed fragment decoding without throwing (#171)
  • cea547c Bumped v3.1.1
  • 876ce79 Merge commit from fork
  • dcdf690 ci: add lock-threads workflow (#169)
  • c860e65 build(deps-dev): bump neostandard from 0.12.2 to 0.13.0 (#167)
  • 9b4c6dc build(deps): bump fastify/workflows/.github/workflows/plugins-ci.yml (#166)
  • 85d09a9 build(deps): bump fastify/workflows/.github/workflows/plugins-ci-package-mana...
  • Additional commits viewable in compare view

Updates `postcss` from 8.5.6 to 8.5.14
Release notes

Sourced from postcss's releases.

8.5.14

8.5.13

  • Fixed postcss-scss commend regression.

8.5.12

  • Fixed reading any file via user-generated CSS.
  • Added opts.unsafeMap to disable checks.

8.5.11

  • Fixed nested brackets parsing performance (by @​offset).

8.5.10

  • Fixed XSS via unescaped </style> in non-bundler cases (by @​TharVid).

8.5.9

  • Speed up source map encoding paring in case of the error.

8.5.8

  • Fixed Processor#version.

8.5.7

  • Improved source map annotation cleaning performance (by CodeAnt AI).
Changelog

Sourced from postcss's changelog.

8.5.14

8.5.13

  • Fixed postcss-scss commend regression.

8.5.12

  • Fixed reading any file via user-generated CSS.
  • Added opts.unsafeMap to disable checks.

8.5.11

  • Fixed nested brackets parsing performance (by @​offset).

8.5.10

  • Fixed XSS via unescaped </style> in non-bundler cases (by @​TharVid).

8.5.9

  • Speed up source map encoding paring in case of the error.

8.5.8

  • Fixed Processor#version.

8.5.7

  • Improved source map annotation cleaning performance (by CodeAnt AI).
Commits
  • 3ec1394 Release 8.5.14 version
  • f2bb827 Update dependencies
  • d75953d Merge pull request #2084 from 43081j/raw-raws-rawing
  • 68bd213 fix: always call raw to retrieve raw values
  • af58cf1 Release 8.5.13 version
  • f227dbd Temporary ignore pnpm 11 config
  • d3abd40 Update dependencies
  • dd06c3e Revert stringifier changes because of the conflict with postcss-scss
  • ae889c8 Try to fix CI
  • e0093e4 Move to pnpm 11
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 470c8575a1..7f483d10a1 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1219,9 +1219,9 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.28.6", @@ -9012,9 +9012,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -14307,9 +14307,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", "funding": [ { "type": "opencollective", From 72cfa2e382b451e6375ddab65d1a025705201f8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 13:30:45 -0400 Subject: [PATCH 376/448] deps: bump github/codeql-action from 4.35.3 to 4.35.4 (#2301) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.3 to 4.35.4.
Release notes

Sourced from github/codeql-action's releases.

v4.35.4

  • Update default CodeQL bundle version to 2.25.4. #3881
Commits
  • 68bde55 Merge pull request #3885 from github/update-v4.35.4-803d9e8c3
  • 9739ad2 Update changelog for v4.35.4
  • 803d9e8 Merge pull request #3883 from github/mbg/test/macro-wrapper
  • 0fd9c7d Merge pull request #3882 from github/dependabot/github_actions/dot-github/wor...
  • 922d6fb Use makeMacro instead of test.macro
  • df77e87 Update test macro snippet
  • 6e3f985 Add wrapper for test.macro
  • e7a347d Merge pull request #3881 from github/update-bundle/codeql-bundle-v2.25.4
  • 17eabb2 Rebuild
  • aaef09c Bump ruby/setup-ruby
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.35.3&new-version=4.35.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 35204b93d1..6b21642156 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/autobuild@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index b22761c884..2b80e84682 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 with: sarif_file: "trivy-results.sarif" From 77c3c45837b2e527849bcae9a3dd42dc6ec80368 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 13:31:08 -0400 Subject: [PATCH 377/448] deps: bump golang.org/x/sys from 0.43.0 to 0.44.0 (#2302) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.43.0 to 0.44.0.
Commits
  • fb1facd windows: avoid uint16 overflow in NewNTUnicodeString
  • 94ad893 windows: add GetIfTable2Ex, GetIpInterface{Entry,Table}, GetUnicastIpAddressT...
  • 54fe89f cpu: use IsProcessorFeaturePresent to calculate ARM64 on windows
  • df7d5d7 unix: automatically remove container created by mkall.sh
  • 68a4a8e unix: avoid nil pointer dereference in Utime
  • 690c91f unix: add CPUSetDynamic for systems with more than 1024 CPUs
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/sys&package-manager=go_modules&previous-version=0.43.0&new-version=0.44.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8a5ad034f7..c0bea249ed 100644 --- a/go.mod +++ b/go.mod @@ -197,7 +197,7 @@ require ( golang.org/x/net v0.53.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.20.0 - golang.org/x/sys v0.43.0 + golang.org/x/sys v0.44.0 golang.org/x/term v0.42.0 // indirect google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 2308275afb..b9eac808bc 100644 --- a/go.sum +++ b/go.sum @@ -1852,8 +1852,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= From 70d66765a96de5a48edba40047601badc75cb92f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 14:59:30 -0400 Subject: [PATCH 378/448] deps: bump the go_modules group across 1 directory with 2 updates (#2305) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the go_modules group with 2 updates in the / directory: [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) and [github.com/in-toto/in-toto-golang](https://github.com/in-toto/in-toto-golang). Updates `github.com/go-git/go-git/v5` from 5.18.0 to 5.19.0
Release notes

Sourced from github.com/go-git/go-git/v5's releases.

v5.19.0

What's Changed

Full Changelog: https://github.com/go-git/go-git/compare/v5.18.0...v5.19.0

Commits
  • bc930f4 Merge pull request #2065 from go-git/commit-v5
  • d315264 plumbing: object, Reset object before decode
  • 6e1d348 plumbing: object, Align Tree handling with upstream
  • e134ba3 tests: Skip double checks in Git v2.11
  • 1971422 tests: Add git conformance tests for signing verification
  • a387aa8 plumbing: object, Add ErrMalformedTag
  • f415670 plumbing: object, Decode Tag headers via a state machine
  • 5b0cd38 plumbing: object, Reject multi-signature commits at Verify
  • fe8ed62 plumbing: object, Align Tag.EncodeWithoutSignature with Commit
  • 98e337d plumbing: object, Add support for Tag.SignatureSHA256
  • Additional commits viewable in compare view

Updates `github.com/in-toto/in-toto-golang` from 0.9.0 to 0.11.0
Release notes

Sourced from github.com/in-toto/in-toto-golang's releases.

v0.11.0

What's Changed

Full Changelog: https://github.com/in-toto/in-toto-golang/compare/v0.10.0...v0.11.0

v0.10.0

What's Changed

... (truncated)

Commits
  • 36d782f Merge pull request #462 from in-toto/fix-negation-character
  • 4a09e3b match: Replace ^ with ! for negation in character classes
  • c3302e8 Merge pull request #459 from in-toto/dependabot/go_modules/github.com/go-jose...
  • 016e87e chore(deps): bump github.com/go-jose/go-jose/v4 from 4.1.3 to 4.1.4
  • 5b9df76 Merge pull request #457 from in-toto/dependabot/go_modules/google.golang.org/...
  • 595b3fe chore(deps): bump google.golang.org/grpc from 1.79.1 to 1.79.3
  • e396d24 Merge pull request #452 from in-toto/dependabot/github_actions/all-502588e1ca
  • 142b779 Merge pull request #453 from in-toto/dependabot/go_modules/all-d8ef5820aa
  • f741bcc chore(deps): bump the all group with 2 updates
  • c374dc9 chore(deps): bump the all group across 1 directory with 2 updates
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index c0bea249ed..c8ad35a0ea 100644 --- a/go.mod +++ b/go.mod @@ -431,8 +431,8 @@ require ( github.com/go-critic/go-critic v0.14.3 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.8.0 // indirect - github.com/go-git/go-git/v5 v5.18.0 // indirect + github.com/go-git/go-billy/v5 v5.9.0 // indirect + github.com/go-git/go-git/v5 v5.19.0 // indirect github.com/go-openapi/swag/cmdutils v0.25.5 // indirect github.com/go-openapi/swag/conv v0.25.5 // indirect github.com/go-openapi/swag/fileutils v0.25.5 // indirect @@ -498,7 +498,7 @@ require ( github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/in-toto/attestation v1.1.2 // indirect - github.com/in-toto/in-toto-golang v0.9.0 // indirect + github.com/in-toto/in-toto-golang v0.11.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-block-format v0.2.0 // indirect @@ -524,7 +524,7 @@ require ( github.com/kevinburke/ssh_config v1.4.0 // indirect github.com/kisielk/errcheck v1.10.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kulti/thelper v0.7.1 // indirect github.com/kunwardeep/paralleltest v1.0.15 // indirect @@ -575,7 +575,7 @@ require ( github.com/onsi/ginkgo v1.16.5 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect + github.com/pjbgf/sha1cd v0.6.0 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect github.com/quasilyte/go-ruleguard v0.4.5 // indirect diff --git a/go.sum b/go.sum index b9eac808bc..81094af560 100644 --- a/go.sum +++ b/go.sum @@ -622,12 +622,12 @@ github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0= -github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= +github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= +github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= -github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.19.0 h1:+WkVUQZSy/F1Gb13udrMKjIM2PrzsNfDKFSfo5tkMtc= +github.com/go-git/go-git/v5 v5.19.0/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= @@ -951,8 +951,8 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/in-toto/attestation v1.1.2 h1:MBFn6lsMq6dptQZJBhalXTcWMb/aJy3V+GX3VYj/V1E= github.com/in-toto/attestation v1.1.2/go.mod h1:gYFddHMZj3DiQ0b62ltNi1Vj5rC879bTmBbrv9CRHpM= -github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU= -github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo= +github.com/in-toto/in-toto-golang v0.11.0 h1:nfidMYBFx+E0lnmX5KUnN2Pdm8zdNKal1ayjJuzzRoA= +github.com/in-toto/in-toto-golang v0.11.0/go.mod h1:u3PjTnwFKjp5a1YCcw8SJg0G+tMeKfVoWsWeFMDCMtw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= @@ -1055,8 +1055,8 @@ github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/tt github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -1299,8 +1299,8 @@ github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe h1:vHpqOnPlnkba8i github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= +github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= +github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From 5bf732e231d1180763dd5c1bf0de9249fa46fd73 Mon Sep 17 00:00:00 2001 From: Chetan Atole Date: Tue, 12 May 2026 00:34:50 +0530 Subject: [PATCH 379/448] build: add empty-bpf-objects target to Makefile (#2297) # Description Adds the missing 'empty-bpf-objects' target mentioned in CI error messages. This allows developers to truncate eBPF .o files to 0-byte stubs after local generation, satisfying the repo policy and fixing GHA 'Generate Check' failures. ## Related Issue Fixes #2291 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed - Ran `make generate-bpf-go` to ensure .o files contained binary data, ran the new `make empty-bpf-objects` target, confirmed the .o files returned to their original 0-byte state, resulting in a clean git status. - Verified make help ``` Utils empty-bpf-objects truncate all tracked .o files to 0 bytes ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Chetan Atole --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 33ab104065..c9314e08ee 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,9 @@ generate-bpf-go: ## generate ebpf wrappers for plugins for all archs FMT_PKG ?= . LINT_PKG ?= . +empty-bpf-objects: ## truncate all tracked .o files to 0 bytes + git ls-files '*.o' | xargs truncate -s 0 + fmt: ## run gofumpt on $FMT_PKG (default "retina"). $(GOFUMPT) -w $(FMT_PKG) From 36ac60d6164ae2f09853ac1d7f4c381a737a52ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 16:43:12 -0400 Subject: [PATCH 380/448] deps: bump sigstore/cosign-installer from 4.1.1 to 4.1.2 (#2292) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.1.1 to 4.1.2.
Release notes

Sourced from sigstore/cosign-installer's releases.

v4.1.2

What's Changed

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-charts.yaml | 2 +- .github/workflows/release-images.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 4d45eaa467..73c9e088a3 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -28,7 +28,7 @@ jobs: id: install - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry (Helm for pushing chart, Docker for signing and push signature) run: | diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index d5a8a653e7..09086407a6 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -38,7 +38,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -135,7 +135,7 @@ jobs: throw "Docker daemon failed to start within $timeout seconds" - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -188,7 +188,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -236,7 +236,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -282,7 +282,7 @@ jobs: - run: go version - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -328,7 +328,7 @@ jobs: uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Install Cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Log in to registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin From 793f2612d461314f534f1cfcceb500368eb9f9d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 20:08:03 -0400 Subject: [PATCH 381/448] deps: bump azurelinux/base/core from `35149ae` to `82e37dd` in /controller (#2312) Bumps azurelinux/base/core from `35149ae` to `82e37dd`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azurelinux/base/core&package-manager=docker&previous-version=3.0&new-version=3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 41f05b6929..a4554003f4 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -4,7 +4,7 @@ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:82e37ddcf271af1b720036697d8ab8c95f7001c3eaf7694a9ca17b35d84085de AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS azurelinux-distroless From 045f143ec8a2f025b398e48f323bb515ef9276c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 00:10:28 +0000 Subject: [PATCH 382/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.19.0 to 0.20.2 (#2294) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.19.0 to 0.20.2.
Commits
  • 5d9f23b chore: bump dependencies against k/k release-1.36 (#10266)
  • 56496d6 build(deps): bump k8s.io/client-go (#10234)
  • b85dbbd build(deps): bump k8s.io/component-base (#10233)
  • ab9a79b build(deps): bump the all group in /tests with 2 updates (#10267)
  • 8aa3303 build(deps): bump sigs.k8s.io/cloud-provider-azure/pkg/azclient (#10255)
  • 5e74e00 build(deps): bump the all group across 1 directory with 2 updates (#10254)
  • 5e6c117 build(deps): bump the all group across 1 directory with 4 updates (#10256)
  • 78f40bc fix: calico chart version race cond (#10265)
  • 6d4dd62 test: add CALICO_VERSION substitution to linux-vmss-ci-version manifest (#10269)
  • eb9eacc test: add CALICO_VERSION substitution to linux-vmss CI manifest (#10268)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.19.0&new-version=0.20.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c8ad35a0ea..53e530c40f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.28.0 k8s.io/client-go v0.35.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.2 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 ) diff --git a/go.sum b/go.sum index 81094af560..57353544c5 100644 --- a/go.sum +++ b/go.sum @@ -2033,8 +2033,8 @@ oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0 h1:dh6aoXX1aofigfsRDZPECa4rat1NBKcE6ZQlhx2F2hY= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.19.0/go.mod h1:qIX6mr9uEnUlC+3BQCjFBR9c4Qj+5mN0hrNZIYdMFWE= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.2 h1:EhAWUKiuFQNvaX5pa5uXR6fYtbc5IcSCgpKOrs1s8LM= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.2/go.mod h1:T/JVRJLNZbG/nOfkij2kIMGHuO23RjY9W6H5IjLvrws= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 h1:yjbZWgLUgTnLCGxM8I88l88WgvLRIOcOmAEbacFVLnU= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0/go.mod h1:6NYpRYlC7AyQaDtOQsF62plL1gDQqJwgQUwTdjp8qlU= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= From 2cc77ed1d00e509c4e36cefd15b3b55f0298bb22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 10:54:32 -0400 Subject: [PATCH 383/448] deps: bump oss/go/microsoft/golang from 1.26.2-azurelinux3.0 to 1.26.3-azurelinux3.0 in /operator (#2313) Bumps oss/go/microsoft/golang from 1.26.2-azurelinux3.0 to 1.26.3-azurelinux3.0. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.3-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index 01fc869817..ea268f7b1e 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 2b77ab6f63..8cbf5c7379 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS builder # Build args ARG VERSION From 4cd377c974e025f54387b191ab0744210d86f00e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 10:54:53 -0400 Subject: [PATCH 384/448] deps: bump oss/go/microsoft/golang from 1.26.2-windowsservercore-ltsc2022 to 1.26.3-windowsservercore-ltsc2022 in /controller (#2316) Bumps oss/go/microsoft/golang from 1.26.2-windowsservercore-ltsc2022 to 1.26.3-windowsservercore-ltsc2022. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index a4554003f4..ee587197a6 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:82e37ddcf271af1b720036697d8ab8c95f7001c3eaf7694a9ca17b35d84085de AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index 91e26a1811..fe20303bf1 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 51fcff84a0..8f0f930218 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 9fd3b71748..7d133022de 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:7dc9ddecd32b6c338f2c9ac9b87f51eb7f1bc603af4fe389abefa0db310a8239 AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:58d69eaa704978128e3ff640db70412786a5100be4999e46c5670bdeea5fb320 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 89faf7717e..9a6d4c22fd 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022@sha256:7dc9ddecd32b6c338f2c9ac9b87f51eb7f1bc603af4fe389abefa0db310a8239 AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:58d69eaa704978128e3ff640db70412786a5100be4999e46c5670bdeea5fb320 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . From a185574fb86c82694bc42beecd1b638184042528 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 12 May 2026 12:28:04 -0400 Subject: [PATCH 385/448] deps: bump hubble CLI to v1.19.3 (#2310) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Bumps the Hubble CLI binary baked into the `retina-agent` image from `v1.18.6` → `v1.19.3` (current upstream stable, released 2026-04-22). This brings the in-image CLI into alignment with `go.mod`, which already pins `github.com/cilium/cilium v1.19.3`. ## Related Issue N/A. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed N/A — version-pin bump only. ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- Makefile | 2 +- controller/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c9314e08ee..fb2183de69 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ PLATFORM ?= $(OS)/$(ARCH) PLATFORMS ?= linux/amd64 linux/arm64 windows/amd64 OS_VERSION ?= ltsc2022 -HUBBLE_VERSION ?= v1.18.6 +HUBBLE_VERSION ?= v1.19.3 CONTAINER_BUILDER ?= docker CONTAINER_RUNTIME ?= docker diff --git a/controller/Dockerfile b/controller/Dockerfile index ee587197a6..705539b7fb 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -90,7 +90,7 @@ RUN cp $(which bpftool) /tmp/init-bin ARG GOARCH=amd64 ENV HUBBLE_ARCH=${GOARCH} # ARG HUBBLE_VERSION may be modified via the update-hubble GitHub Action -ARG HUBBLE_VERSION=v1.18.6 +ARG HUBBLE_VERSION=v1.19.3 ENV HUBBLE_VERSION=${HUBBLE_VERSION} RUN echo "Hubble version: $HUBBLE_VERSION" && \ wget --no-check-certificate https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz && \ From 5e1fba626c6b4a208d610016757bf478b3549062 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Tue, 12 May 2026 14:26:50 -0400 Subject: [PATCH 386/448] fix(chart): roll operator pod when its configmap changes (#2162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description The operator Deployment's pod template has no `checksum/config` annotation, so `helm upgrade` doesn't roll the operator when its ConfigMap rendering changes. The operator reads its config once at startup and caches it, so values like `remoteContext` stay stale until the pod is manually restarted — leaving the operator unable to create `retinaendpoint` resources that agents in remote-context mode rely on. This PR adds the annotation, matching what `daemonset.yaml` already does. The operator ConfigMap is split out of `operator.yaml` into its own `operator-configmap.yaml` so the `include` used by the checksum doesn't recurse into itself. Found while testing #2152 on a live cluster. ## Related Issue Relates to #2152 ## Checklist - [x] I have read the [contributing guidelines](../CONTRIBUTING.md) - [x] I have signed the CLA - [ ] Unit tests added/updated — N/A, chart template change - [ ] Integration tests added/updated — N/A, chart template change - [ ] Documentation updated — N/A - [x] Helm chart updated ## Testing ```bash helm lint deploy/standard/manifests/controller/helm/retina/ # 1 chart(s) linted, 0 chart(s) failed ``` Verified the checksum annotation actually moves when operator config values change: ```bash HASH1=$(helm template test deploy/standard/manifests/controller/helm/retina/ \ --set operator.enabled=true --set remoteContext=false | grep 'checksum/config' | tail -1) HASH2=$(helm template test deploy/standard/manifests/controller/helm/retina/ \ --set operator.enabled=true --set remoteContext=true | grep 'checksum/config' | tail -1) # different → pod will roll on the next helm upgrade ``` Signed-off-by: Quang Nguyen --- .../retina/templates/operator-configmap.yaml | 19 ++++++++++++++++ .../helm/retina/templates/operator.yaml | 22 ++++--------------- 2 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml diff --git a/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml new file mode 100644 index 0000000000..19d68b0298 --- /dev/null +++ b/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml @@ -0,0 +1,19 @@ +{{- if .Values.operator.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ .Values.operator.name }}-config" + namespace: {{ .Values.namespace }} +data: + operator-config.yaml: |- + installCRDs: {{ .Values.operator.installCRDs }} + enableTelemetry: {{ .Values.enableTelemetry }} + remoteContext: {{ .Values.remoteContext }} + captureDebug: {{ .Values.capture.debug }} + captureJobNumLimit: {{ .Values.capture.jobNumLimit }} + enableManagedStorageAccount: {{ .Values.capture.enableManagedStorageAccount }} + telemetryInterval: {{ .Values.operator.telemetryInterval }} +{{- if .Values.capture.enableManagedStorageAccount }} + azureCredentialConfig: /etc/cloud-config/azure.json +{{- end }} +{{- end }} diff --git a/deploy/standard/manifests/controller/helm/retina/templates/operator.yaml b/deploy/standard/manifests/controller/helm/retina/templates/operator.yaml index c63c07e8fb..693538e4c1 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/operator.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/operator.yaml @@ -24,6 +24,10 @@ spec: kubectl.kubernetes.io/default-container: {{ .Values.operator.name }} prometheus.io/port: "{{ .Values.operatorService.port }}" prometheus.io/scrape: "true" + # Roll the operator pod whenever its ConfigMap rendering changes, + # so `helm upgrade` applies new config values (e.g. `remoteContext`) + # without requiring a manual `kubectl rollout restart`. + checksum/config: {{ include (print $.Template.BasePath "/operator-configmap.yaml") . | sha256sum }} labels: app: {{ .Values.operator.name }} control-plane: {{ .Values.operator.name }} @@ -283,24 +287,6 @@ subjects: name: {{ .Values.operator.name }} namespace: {{ .Values.namespace }} --- -apiVersion: v1 -kind: ConfigMap -metadata: - name: "{{ .Values.operator.name }}-config" - namespace: {{ .Values.namespace }} -data: - operator-config.yaml: |- - installCRDs: {{ .Values.operator.installCRDs }} - enableTelemetry: {{ .Values.enableTelemetry }} - remoteContext: {{ .Values.remoteContext }} - captureDebug: {{ .Values.capture.debug }} - captureJobNumLimit: {{ .Values.capture.jobNumLimit }} - enableManagedStorageAccount: {{ .Values.capture.enableManagedStorageAccount }} - telemetryInterval: {{ .Values.operator.telemetryInterval }} -{{- if .Values.capture.enableManagedStorageAccount }} - azureCredentialConfig: /etc/cloud-config/azure.json -{{- end }} ---- {{- if .Values.capture.enableManagedStorageAccount }} apiVersion: v1 kind: Secret From 79e4a7a77c5b17e0a8649922674ccb622c19848b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 15:17:32 -0400 Subject: [PATCH 387/448] deps: bump oss/go/microsoft/golang from 1.26.2-azurelinux3.0 to 1.26.3-azurelinux3.0 in /cli (#2319) Bumps oss/go/microsoft/golang from 1.26.2-azurelinux3.0 to 1.26.3-azurelinux3.0. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=oss/go/microsoft/golang&package-manager=docker&previous-version=1.26.2-azurelinux3.0&new-version=1.26.3-azurelinux3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 207ac25c29..98d47ded9c 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS builder ARG VERSION ARG APP_INSIGHTS_ID From 837b893bdf1da1b23ccabcd922449a347382f2f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 15:17:50 -0400 Subject: [PATCH 388/448] deps: bump golang.org/x/mod from 0.35.0 to 0.36.0 (#2311) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.35.0 to 0.36.0.
Commits
  • 643da9b go.mod: update golang.org/x dependencies
  • ccc3cdf zip: include 'but content has correct sum' note in TestVCS
  • ab30318 zip: update zip hashes for new flate compression
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/mod&package-manager=go_modules&previous-version=0.35.0&new-version=0.36.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 53e530c40f..0fed78bc2d 100644 --- a/go.mod +++ b/go.mod @@ -168,7 +168,7 @@ require ( go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect golang.org/x/crypto v0.50.0 // indirect - golang.org/x/mod v0.35.0 + golang.org/x/mod v0.36.0 golang.org/x/text v0.36.0 // indirect golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.44.0 // indirect diff --git a/go.sum b/go.sum index 57353544c5..001881bc05 100644 --- a/go.sum +++ b/go.sum @@ -1747,8 +1747,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From dc5e47e741a25bf7be94c3d1dfecd67b0ea77ba5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 20:35:29 -0400 Subject: [PATCH 389/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.20.2 to 0.20.3 (#2323) Bumps [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure) from 0.20.2 to 0.20.3.
Commits
  • 675b07a build(deps): bump the all group in /pkg/azclient with 2 updates (#10312)
  • 2b62574 build(deps): bump actions/dependency-review-action in the all group (#10314)
  • 3107197 fix: add .go-version generation to vendor license scripts (#10301)
  • 1fb8674 cleanup: remove unused load balancer production paths (#10299)
  • da1d145 chore: update vendor licences (#10294)
  • bdd08ca build(deps): bump sigs.k8s.io/cloud-provider-azure/pkg/azclient (#10278)
  • fcdab32 build(deps): bump sigs.k8s.io/controller-tools (#10277)
  • 7702288 build(deps): bump github/codeql-action in the all group (#10289)
  • 850aafd build(deps): bump github.com/go-git/go-git/v5 (#10279)
  • c568a2d chore: enable dependabot for release-1.36 (#10272)
  • See full diff in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 0fed78bc2d..b893abfc80 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.28.0 k8s.io/client-go v0.35.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.2 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.3 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 ) @@ -167,9 +167,9 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.uber.org/dig v1.17.1 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.50.0 // indirect + golang.org/x/crypto v0.51.0 // indirect golang.org/x/mod v0.36.0 - golang.org/x/text v0.36.0 // indirect + golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.44.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect @@ -194,11 +194,11 @@ require ( github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/net v0.54.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.20.0 golang.org/x/sys v0.44.0 - golang.org/x/term v0.42.0 // indirect + golang.org/x/term v0.43.0 // indirect google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.35.4 diff --git a/go.sum b/go.sum index 001881bc05..955a03ca0d 100644 --- a/go.sum +++ b/go.sum @@ -1722,8 +1722,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= @@ -1780,8 +1780,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= @@ -1861,8 +1861,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1872,8 +1872,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2033,8 +2033,8 @@ oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.2 h1:EhAWUKiuFQNvaX5pa5uXR6fYtbc5IcSCgpKOrs1s8LM= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.2/go.mod h1:T/JVRJLNZbG/nOfkij2kIMGHuO23RjY9W6H5IjLvrws= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.3 h1:Dil9+oiwQPA7odxzOvdconusdXU7ZNRKZvwO70q8V30= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.3/go.mod h1:YnLuHCYfiPHR3QgWM8dXJk/hYC4pLr2mOOVyJsYqTYQ= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 h1:yjbZWgLUgTnLCGxM8I88l88WgvLRIOcOmAEbacFVLnU= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0/go.mod h1:6NYpRYlC7AyQaDtOQsF62plL1gDQqJwgQUwTdjp8qlU= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= From 79e9c2b52f9c32085cc7152d64aa909ecdaee253 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 20:42:43 -0400 Subject: [PATCH 390/448] deps: bump azurelinux/distroless/minimal from `5a66f9f` to `4c30ebf` in /operator (#2315) Bumps azurelinux/distroless/minimal from `5a66f9f` to `4c30ebf`. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator/Dockerfile b/operator/Dockerfile index ea268f7b1e..69b773df8e 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -25,7 +25,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ ##################### controller ####################### # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:4c30ebfa41297a79e98dc08117cc17e80245aacff9dfd0578cbc8c75c2368566 WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib From 162d19ede7bb4dbc1a10ff1fc6de384258964a1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 10:42:50 -0400 Subject: [PATCH 391/448] deps: bump azurelinux/base/core from `35149ae` to `82e37dd` in /shell (#2321) Bumps azurelinux/base/core from `35149ae` to `82e37dd`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azurelinux/base/core&package-manager=docker&previous-version=3.0&new-version=3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- shell/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/Dockerfile b/shell/Dockerfile index deedfdb9be..aa6f70d433 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b +FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:82e37ddcf271af1b720036697d8ab8c95f7001c3eaf7694a9ca17b35d84085de RUN tdnf install -y \ bind-utils \ From f0dca28715bcc028b53deda9247cec59d6706993 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 11:05:25 -0400 Subject: [PATCH 392/448] deps: bump azurelinux/base/core from `82e37dd` to `9230290` in /controller (#2334) Bumps azurelinux/base/core from `82e37dd` to `9230290`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azurelinux/base/core&package-manager=docker&previous-version=3.0&new-version=3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/Dockerfile b/controller/Dockerfile index 705539b7fb..e62c6880aa 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -4,7 +4,7 @@ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:82e37ddcf271af1b720036697d8ab8c95f7001c3eaf7694a9ca17b35d84085de AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:9230290079612a2a8d30a0aa8b8f097c3194e787d09987df0c3e6b8f6271ee27 AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS azurelinux-distroless From f59a1a5e923dd7a1424eed9c4ddc86066df60b61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 11:38:44 -0400 Subject: [PATCH 393/448] deps: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.100.1 to 1.101.0 (#2293) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.100.1 to 1.101.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/service/s3&package-manager=go_modules&previous-version=1.100.1&new-version=1.101.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b893abfc80..7b57355f7e 100644 --- a/go.mod +++ b/go.mod @@ -227,7 +227,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.17 github.com/aws/aws-sdk-go-v2/credentials v1.19.16 - github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 + github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 github.com/cilium/cilium v1.19.3 github.com/cilium/ebpf v0.21.0 diff --git a/go.sum b/go.sum index 955a03ca0d..c5a7ab848a 100644 --- a/go.sum +++ b/go.sum @@ -289,8 +289,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 h1:03xatSQO4+AM1 github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23/go.mod h1:M8l3mwgx5ToK7wot2sBBce/ojzgnPzZXUV445gTSyE8= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 h1:mxuT1xE+dI54NW3RkNjP8DUT5HXqbkiAFvfdyDFwE5c= -github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 h1:etqBTKY581iwLL/H/S2sVgk3C9lAsTJFeXWFDsDcWOU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= From 6f9f893560a6b2fa66e78b116a76d74e84643cb5 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 13 May 2026 12:01:35 -0400 Subject: [PATCH 394/448] feat(e2e): make agent pool VM SKUs configurable via env (#2308) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Agent pool VM SKUs are hardcoded today (`Standard_D4ds_v4` for Linux and Windows, `Standard_D4pds_v5` for Linux ARM). When a SKU is suddenly made unavailable in a region without prior notice, the workflow has no escape hatch short of a code change. This PR mirrors the existing `AZURE_LOCATION` pattern: three env vars override the in-code defaults, plumbed through the workflows as optional inputs and repo variables. | OS / arch | Env var | Default | |---|---|---| | Linux x86 | `AZURE_AGENT_LINUX_SKU` | `Standard_D4ds_v4` | | Linux ARM64 | `AZURE_AGENT_LINUX_ARM_SKU` | `Standard_D4pds_v5` | | Windows | `AZURE_AGENT_WINDOWS_SKU` | `Standard_D4ds_v4` | When an env var is unset or empty, the Go code falls back to the in-code default — so this is a no-op until a repo variable (e.g. `vars.AZURE_AGENT_LINUX_SKU`) is set. ## Changes - **Go**: new `test/e2e/framework/azure/skus.go` declares `AgentLinuxSKU`, `AgentLinuxARMSKU`, `AgentWindowsSKU` as env-overridable vars. Callers in `create-cluster.go`, `create-cluster-with-npm.go`, and `scale.go` now reference them instead of the previous constants and one hardcoded string. - **Workflows**: `perf-template.yaml`, `perf-manual.yaml`, `perf-schedule.yaml`, `images.yaml`, and `e2e.yaml` get three optional inputs each plus env wiring. Caller workflows pass `vars.AZURE_AGENT_LINUX_SKU` etc. ## Related Issue N/A. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed `go build ./test/e2e/...`, `go vet ./test/e2e/...`, and YAML parse all clean on the touched files. ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- .github/workflows/e2e.yaml | 33 +++++++++++++++++++ .github/workflows/images.yaml | 9 +++++ .github/workflows/perf-manual.yaml | 3 ++ .github/workflows/perf-schedule.yaml | 6 ++++ .github/workflows/perf-template.yaml | 18 ++++++++++ .../azure/create-cluster-with-npm.go | 5 ++- test/e2e/framework/azure/create-cluster.go | 4 +-- test/e2e/framework/azure/skus.go | 16 +++++++++ test/e2e/jobs/scale.go | 2 +- 9 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 test/e2e/framework/azure/skus.go diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index f35c2841fb..e7e6322f3a 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -19,6 +19,21 @@ on: required: true type: string description: The Azure location to use for the E2E tests. + azure_agent_linux_sku: + required: false + default: '' + type: string + description: VM SKU for the Linux agent pool. Falls back to the in-code default when empty. + azure_agent_windows_sku: + required: false + default: '' + type: string + description: VM SKU for the Windows agent pool. Falls back to the in-code default when empty. + azure_agent_linux_arm_sku: + required: false + default: '' + type: string + description: VM SKU for the ARM64 agent pool. Falls back to the in-code default when empty. use_existing_infra: required: false default: false @@ -61,6 +76,21 @@ on: required: false type: string description: The Azure location to use for the E2E tests. + azure_agent_linux_sku: + required: false + default: '' + type: string + description: VM SKU for the Linux agent pool. Falls back to the in-code default when empty. + azure_agent_windows_sku: + required: false + default: '' + type: string + description: VM SKU for the Windows agent pool. Falls back to the in-code default when empty. + azure_agent_linux_arm_sku: + required: false + default: '' + type: string + description: VM SKU for the ARM64 agent pool. Falls back to the in-code default when empty. use_existing_infra: required: false default: false @@ -108,6 +138,9 @@ jobs: env: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION }} AZURE_LOCATION: ${{ inputs.azure_location }} + AZURE_AGENT_LINUX_SKU: ${{ inputs.azure_agent_linux_sku }} + AZURE_AGENT_WINDOWS_SKU: ${{ inputs.azure_agent_windows_sku }} + AZURE_AGENT_LINUX_ARM_SKU: ${{ inputs.azure_agent_linux_arm_sku }} shell: bash run: | set -euo pipefail diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index f62ce76412..29b2e1faf5 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -422,6 +422,9 @@ jobs: env: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} + AZURE_AGENT_LINUX_SKU: ${{ vars.AZURE_AGENT_LINUX_SKU }} + AZURE_AGENT_WINDOWS_SKU: ${{ vars.AZURE_AGENT_WINDOWS_SKU }} + AZURE_AGENT_LINUX_ARM_SKU: ${{ vars.AZURE_AGENT_LINUX_ARM_SKU }} shell: bash run: | set -euo pipefail @@ -446,6 +449,9 @@ jobs: image-namespace: ${{ github.repository }} retina-mode: basic azure-location: ${{ vars.AZURE_LOCATION }} + azure-agent-linux-sku: ${{ vars.AZURE_AGENT_LINUX_SKU }} + azure-agent-windows-sku: ${{ vars.AZURE_AGENT_WINDOWS_SKU }} + azure-agent-linux-arm-sku: ${{ vars.AZURE_AGENT_LINUX_ARM_SKU }} secrets: azure-subscription: ${{ secrets.AZURE_SUBSCRIPTION }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -462,6 +468,9 @@ jobs: image-namespace: ${{ github.repository }} retina-mode: advanced azure-location: ${{ vars.AZURE_LOCATION }} + azure-agent-linux-sku: ${{ vars.AZURE_AGENT_LINUX_SKU }} + azure-agent-windows-sku: ${{ vars.AZURE_AGENT_WINDOWS_SKU }} + azure-agent-linux-arm-sku: ${{ vars.AZURE_AGENT_LINUX_ARM_SKU }} secrets: azure-subscription: ${{ secrets.AZURE_SUBSCRIPTION }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} diff --git a/.github/workflows/perf-manual.yaml b/.github/workflows/perf-manual.yaml index 1660987969..0aabe614fd 100644 --- a/.github/workflows/perf-manual.yaml +++ b/.github/workflows/perf-manual.yaml @@ -35,6 +35,9 @@ jobs: image-namespace: ${{ inputs.image-namespace || github.repository }} retina-mode: ${{ inputs.retina-mode }} azure-location: ${{ vars.AZURE_LOCATION }} + azure-agent-linux-sku: ${{ vars.AZURE_AGENT_LINUX_SKU }} + azure-agent-windows-sku: ${{ vars.AZURE_AGENT_WINDOWS_SKU }} + azure-agent-linux-arm-sku: ${{ vars.AZURE_AGENT_LINUX_ARM_SKU }} secrets: azure-subscription: ${{ secrets.AZURE_SUBSCRIPTION }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} diff --git a/.github/workflows/perf-schedule.yaml b/.github/workflows/perf-schedule.yaml index 92eed22c78..851dd1105e 100644 --- a/.github/workflows/perf-schedule.yaml +++ b/.github/workflows/perf-schedule.yaml @@ -34,6 +34,9 @@ jobs: image-namespace: ${{ github.repository }} retina-mode: basic azure-location: ${{ vars.AZURE_LOCATION }} + azure-agent-linux-sku: ${{ vars.AZURE_AGENT_LINUX_SKU }} + azure-agent-windows-sku: ${{ vars.AZURE_AGENT_WINDOWS_SKU }} + azure-agent-linux-arm-sku: ${{ vars.AZURE_AGENT_LINUX_ARM_SKU }} secrets: azure-subscription: ${{ secrets.AZURE_SUBSCRIPTION }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -49,6 +52,9 @@ jobs: image-namespace: ${{ github.repository }} retina-mode: advanced azure-location: ${{ vars.AZURE_LOCATION }} + azure-agent-linux-sku: ${{ vars.AZURE_AGENT_LINUX_SKU }} + azure-agent-windows-sku: ${{ vars.AZURE_AGENT_WINDOWS_SKU }} + azure-agent-linux-arm-sku: ${{ vars.AZURE_AGENT_LINUX_ARM_SKU }} secrets: azure-subscription: ${{ secrets.AZURE_SUBSCRIPTION }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index f232d9e932..3f391302a0 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -24,6 +24,21 @@ on: description: 'Azure location for the performance test' required: true type: string + azure-agent-linux-sku: + description: 'VM SKU for the Linux agent pool' + required: false + default: '' + type: string + azure-agent-windows-sku: + description: 'VM SKU for the Windows agent pool' + required: false + default: '' + type: string + azure-agent-linux-arm-sku: + description: 'VM SKU for the ARM64 agent pool' + required: false + default: '' + type: string secrets: azure-subscription: description: 'Azure subscription ID' @@ -71,6 +86,9 @@ jobs: AZURE_APP_INSIGHTS_KEY: ${{ secrets.azure-app-insights-key }} AZURE_SUBSCRIPTION_ID: ${{ secrets.azure-subscription }} AZURE_LOCATION: ${{ inputs.azure-location }} + AZURE_AGENT_LINUX_SKU: ${{ inputs.azure-agent-linux-sku }} + AZURE_AGENT_WINDOWS_SKU: ${{ inputs.azure-agent-windows-sku }} + AZURE_AGENT_LINUX_ARM_SKU: ${{ inputs.azure-agent-linux-arm-sku }} shell: bash run: | set -euo pipefail diff --git a/test/e2e/framework/azure/create-cluster-with-npm.go b/test/e2e/framework/azure/create-cluster-with-npm.go index bcd11c59c1..f560376cba 100644 --- a/test/e2e/framework/azure/create-cluster-with-npm.go +++ b/test/e2e/framework/azure/create-cluster-with-npm.go @@ -21,7 +21,6 @@ const ( clusterTimeout = 15 * time.Minute clusterCreateTicker = 30 * time.Second pollFrequency = 5 * time.Second - AgentARMSKU = "Standard_D4pds_v5" AuxilaryNodeCount = 1 AuxilaryARMNodeCount = 2 ) @@ -77,7 +76,7 @@ func (c *CreateNPMCluster) Run() error { OSType: to.Ptr(armcontainerservice.OSTypeLinux), OSSKU: to.Ptr(armcontainerservice.OSSKUAzureLinux), ScaleDownMode: to.Ptr(armcontainerservice.ScaleDownModeDelete), - VMSize: to.Ptr(AgentSKU), + VMSize: to.Ptr(AgentLinuxSKU), Name: to.Ptr("azlinux"), MaxPods: to.Ptr(int32(MaxPodsPerNode)), }) @@ -90,7 +89,7 @@ func (c *CreateNPMCluster) Run() error { Mode: to.Ptr(armcontainerservice.AgentPoolModeUser), OSType: to.Ptr(armcontainerservice.OSTypeLinux), ScaleDownMode: to.Ptr(armcontainerservice.ScaleDownModeDelete), - VMSize: to.Ptr(AgentARMSKU), + VMSize: to.Ptr(AgentLinuxARMSKU), Name: to.Ptr("arm64"), MaxPods: to.Ptr(int32(MaxPodsPerNode)), }) diff --git a/test/e2e/framework/azure/create-cluster.go b/test/e2e/framework/azure/create-cluster.go index f390b37738..abe085d88e 100644 --- a/test/e2e/framework/azure/create-cluster.go +++ b/test/e2e/framework/azure/create-cluster.go @@ -14,8 +14,6 @@ import ( const ( MaxNumberOfNodes = 3 MaxPodsPerNode = 250 - AgentSKU = "Standard_D4ds_v4" - AgentWindowsSKU = "Standard_D4ds_v4" ) var defaultClusterCreateTimeout = 30 * time.Minute @@ -117,7 +115,7 @@ func GetStarterClusterTemplate(location string) armcontainerservice.ManagedClust Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem), OSType: to.Ptr(armcontainerservice.OSTypeLinux), ScaleDownMode: to.Ptr(armcontainerservice.ScaleDownModeDelete), - VMSize: to.Ptr(AgentSKU), + VMSize: to.Ptr(AgentLinuxSKU), Name: to.Ptr("nodepool1"), MaxPods: to.Ptr(int32(MaxPodsPerNode)), }, diff --git a/test/e2e/framework/azure/skus.go b/test/e2e/framework/azure/skus.go new file mode 100644 index 0000000000..d2885f63f3 --- /dev/null +++ b/test/e2e/framework/azure/skus.go @@ -0,0 +1,16 @@ +package azure + +import "os" + +var ( + AgentLinuxSKU = skuFromEnv("AZURE_AGENT_LINUX_SKU", "Standard_D4ds_v4") + AgentLinuxARMSKU = skuFromEnv("AZURE_AGENT_LINUX_ARM_SKU", "Standard_D4pds_v5") + AgentWindowsSKU = skuFromEnv("AZURE_AGENT_WINDOWS_SKU", "Standard_D4ds_v4") +) + +func skuFromEnv(key, def string) string { + if v := os.Getenv(key); v != "" { + return v + } + return def +} diff --git a/test/e2e/jobs/scale.go b/test/e2e/jobs/scale.go index 31b18a3ad5..b2eede6b75 100644 --- a/test/e2e/jobs/scale.go +++ b/test/e2e/jobs/scale.go @@ -62,7 +62,7 @@ func GetScaleTestInfra(subID, rg, clusterName, location, kubeConfigFilePath stri Nodes: nodes, }). SetPodCidr("100.64.0.0/10"). - SetVMSize("Standard_D4ds_v4"). + SetVMSize(azure.AgentLinuxSKU). SetNetworkPluginMode("overlay"), nil) job.AddStep(&azure.GetAKSKubeConfig{ From 912708d268fc44e0e761875784be4b413de0d327 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 13 May 2026 13:50:52 -0400 Subject: [PATCH 395/448] fix(devcontainer): bump go feature to 1.3.4 for golangci-lint fix (#2309) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The DevContainer workflow has been failing on every run since 2026-04-30 because the `ghcr.io/devcontainers/features/go:1.3.3` install script downloads `golangci-lint` v2.12.1+, which now ships an SBOM asset (`…tar.gz.sbom.json`). The deprecated `master/install.sh` greps `checksums.txt` by tarball basename, the SBOM filename matches as a prefix, and the multi-line result fails `hash_sha256_verify` — even though the actual tarball hash is correct. The fix is upstream: [devcontainers/features#1636](https://github.com/devcontainers/features/pull/1636) (merged 2026-05-05) switched the Go feature's install URL to the supported `golangci-lint.run/install.sh` and bumped the feature to **`1.3.4`**. This PR bumps our pin so the next devcontainer build picks it up. Related upstream issues: [golangci/golangci-lint#6572](https://github.com/golangci/golangci-lint/issues/6572), [devcontainers/features#1635](https://github.com/devcontainers/features/issues/1635). ## Related Issue N/A. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed N/A — version-pin bump only. Will validate once the DevContainer workflow runs on this PR. ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5a1882210a..d38af3fb6d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "features": { "ghcr.io/devcontainers/features/docker-in-docker:2.16.1": {}, "ghcr.io/devcontainers/features/github-cli:1.1.0": {}, - "ghcr.io/devcontainers/features/go:1.3.3": { + "ghcr.io/devcontainers/features/go:1.3.4": { "version": "1.24.11" }, "ghcr.io/devcontainers/features/kubectl-helm-minikube:1.3.1": {}, From befa4c7785ecc4698c0ee3e63858aefd436b49c8 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 13 May 2026 13:52:05 -0400 Subject: [PATCH 396/448] chore(deps): consolidate armnetwork to v5 in e2e tests (#2307) # Description `armnetwork` v1.1.0 was only used by `test/e2e/framework/azure/create-public-ip.go` and `test/e2e/jobs/jobs.go`, while the sibling `create-vnet.go` already imports `armnetwork/v5`. Switch the two stragglers to v5 and `go mod tidy` drops the v1.1.0 entry. All symbols used (`NewPublicIPAddressesClient`, `PublicIPAddress*`, `IPVersionIPv{4,6}`, `IPTag`, `IPAllocationMethodStatic`) exist unchanged in v5. Side effect: clears Dependabot's "dependency graph incomplete" warning, which was caused by a `git fetch --unshallow` flake on the v1.1.0 tag. image ## Related Issue N/A. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed `go build` and `go vet` pass for the touched packages: ```bash go build ./test/e2e/framework/azure/... ./test/e2e/jobs/... go vet ./test/e2e/framework/azure/... ./test/e2e/jobs/... ``` ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- go.mod | 1 - go.sum | 4 ---- test/e2e/framework/azure/create-public-ip.go | 2 +- test/e2e/jobs/jobs.go | 2 +- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 7b57355f7e..292125beb8 100644 --- a/go.mod +++ b/go.mod @@ -218,7 +218,6 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 diff --git a/go.sum b/go.sum index c5a7ab848a..e64f4428b0 100644 --- a/go.sum +++ b/go.sum @@ -95,8 +95,6 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontai github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6 v6.6.0/go.mod h1:OWKfCmX4X3Vp2w7GSx1LZn8566tOHJBA6K0IAUVNYx0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 h1:MRPU8Bge2f9tkfG3PCr4vEnqXl8XOSjlhuK3l+8Hvkc= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0/go.mod h1:xYrOYxajQvXMlp6M1E3amlaqPDXspyJxmjqTsGo6Jmw= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0/go.mod h1:ceIuwmxDWptoW3eCqSXlnPsZFKh4X+R38dWPv7GS9Vs= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw= @@ -109,8 +107,6 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0/go.mod h1:jj6P8ybImR+5topJ+eH6fgcemSFBmU6/6bFF8KkwuDI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0 h1:L7G3dExHBgUxsO3qpTGhk/P2dgnYyW48yn7AO33Tbek= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0/go.mod h1:Ms6gYEy0+A2knfKrwdatsggTXYA2+ICKug8w7STorFw= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 h1:qBlqTo40ARdI7Pmq+enBiTnejZk2BF+PHgktgG8k3r8= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0/go.mod h1:UmyOatRyQodVpp55Jr5WJmnkmVW4wKfo85uHFmMEjfM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v9 v9.0.0 h1:CbHDMVJhcJSmXenq+UDWyIjumzVkZIb5pVUGzsCok5M= diff --git a/test/e2e/framework/azure/create-public-ip.go b/test/e2e/framework/azure/create-public-ip.go index 0605e1f74f..135e856da4 100644 --- a/test/e2e/framework/azure/create-public-ip.go +++ b/test/e2e/framework/azure/create-public-ip.go @@ -9,7 +9,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" + armnetwork "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" ) type CreatePublicIP struct { diff --git a/test/e2e/jobs/jobs.go b/test/e2e/jobs/jobs.go index fb820c4faa..c54ab1f8a4 100644 --- a/test/e2e/jobs/jobs.go +++ b/test/e2e/jobs/jobs.go @@ -3,7 +3,7 @@ package retina import ( "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" + armnetwork "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" "github.com/microsoft/retina/test/e2e/common" "github.com/microsoft/retina/test/e2e/framework/azure" "github.com/microsoft/retina/test/e2e/framework/generic" From e2084acb40f13a5032a218f9334db37cfc568f6a Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Wed, 13 May 2026 13:52:15 -0400 Subject: [PATCH 397/448] fix(deps): correct dependabot config (#2306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Two fixes to `.github/dependabot.yaml`: 1. **Drop `cooldown.semver-major-days`** from the docker and github-actions blocks. Dependabot rejects the whole config at parse time because `semver-major-days` is only valid for ecosystems with a real semver model (gomod, npm). `default-days` stays. image 2. **Group docker base image bumps across directories.** Add `group-by: "dependency-name"` to each Docker family group (`golang-base`, `azurelinux-base`, `windows-base`, `ubuntu-base`) so the same base image bump across `/controller`, `/operator`, `/cli`, `/shell`, `/test/image`, and `/hack/tools/*` lands in a single PR instead of one per Dockerfile. Without it, the family patterns only deduplicate within a single directory job. ## Related Issue N/A. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (\`git commit -S -s ...\`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed N/A — config-only change. ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- .github/dependabot.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 73a543a3d1..6a6d9df620 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -20,16 +20,19 @@ updates: open-pull-requests-limit: 10 cooldown: default-days: 7 - semver-major-days: 30 groups: golang-base: patterns: ["*golang*"] + group-by: "dependency-name" azurelinux-base: patterns: ["*azurelinux*"] + group-by: "dependency-name" windows-base: patterns: ["*windows*", "*nanoserver*", "*servercore*"] + group-by: "dependency-name" ubuntu-base: patterns: ["*ubuntu*"] + group-by: "dependency-name" # GitHub Actions - package-ecosystem: "github-actions" @@ -44,7 +47,6 @@ updates: open-pull-requests-limit: 10 cooldown: default-days: 3 - semver-major-days: 14 groups: actions-patch: update-types: ["patch"] From a05b1d5ee3dafa7d10cf478a924149266e6557b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 15:21:06 -0400 Subject: [PATCH 398/448] deps: bump @docusaurus/preset-classic from 3.9.2 to 3.10.1 in /site (#2340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 3.9.2 to 3.10.1.
Release notes

Sourced from @​docusaurus/preset-classic's releases.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Changelog

Sourced from @​docusaurus/preset-classic's changelog.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Commits
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​docusaurus/preset-classic since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@docusaurus/preset-classic&package-manager=npm_and_yarn&previous-version=3.9.2&new-version=3.10.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 5839 +++++++++++++++++++++++++++++++++++++--- site/package.json | 2 +- 2 files changed, 5415 insertions(+), 426 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 7f483d10a1..a1eb316bc1 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -11,7 +11,7 @@ "@docusaurus/core": "^3.9.2", "@docusaurus/plugin-client-redirects": "^3.9.2", "@docusaurus/plugin-ideal-image": "^3.9.2", - "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", "@types/react": "^18.3.28", "clsx": "^2.1.1", @@ -35,46 +35,46 @@ } }, "node_modules/@algolia/abtesting": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.14.1.tgz", - "integrity": "sha512-Dkj0BgPiLAaim9sbQ97UKDFHJE/880wgStAM18U++NaJ/2Cws34J5731ovJifr6E3Pv4T2CqvMXf8qLCC417Ew==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.18.1.tgz", + "integrity": "sha512-aehCadlWOGvrT91KUIZpC0MbB8KBW9yUuvTJFd2xesR7le/IsT4nJUnjCCZ4ZqZCeTcPHPV5mo//fZ5oxcSVYw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", - "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.8.tgz", + "integrity": "sha512-3YEorYg44niXcm7gkft3nXYItHd44e8tmh4D33CTszPgP0QWkaLEaFywiNyJBo7UL/mqObA/G9RYuU7R8tN1IA==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", - "@algolia/autocomplete-shared": "1.19.2" + "@algolia/autocomplete-plugin-algolia-insights": "1.19.8", + "@algolia/autocomplete-shared": "1.19.8" } }, "node_modules/@algolia/autocomplete-plugin-algolia-insights": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", - "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.8.tgz", + "integrity": "sha512-ZvJWO8ZZJDpc1LNM2TTBdmQsZBLMR4rU5iNR2OYvEeFBiaf/0ESnRSSLQbryarJY4SVxtoz6A2ZtDMNM+iQEAA==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.19.2" + "@algolia/autocomplete-shared": "1.19.8" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", - "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.8.tgz", + "integrity": "sha512-h5hf2t8ejF6vlOgvLaZzQbWs5SyH2z4PAWygNAvvD/2RI29hdQ54ldUGwqVuj9Srs+n8XUKTPUqb7fvhBhQrnQ==", "license": "MIT", "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -82,99 +82,99 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.48.1.tgz", - "integrity": "sha512-LV5qCJdj+/m9I+Aj91o+glYszrzd7CX6NgKaYdTOj4+tUYfbS62pwYgUfZprYNayhkQpVFcrW8x8ZlIHpS23Vw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.52.1.tgz", + "integrity": "sha512-HmXOGBOAOJPounpBzBpuY0zDYeiCpxgHnQmuA7JO6ScukcBdGp3/XM9zJk5pJx/xNGD68mbPGXWpDxGtl6BwDQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.48.1.tgz", - "integrity": "sha512-/AVoMqHhPm14CcHq7mwB+bUJbfCv+jrxlNvRjXAuO+TQa+V37N8k1b0ijaRBPdmSjULMd8KtJbQyUyabXOu6Kg==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.52.1.tgz", + "integrity": "sha512-5oo4+I8iixie9vXhCyNFCzeIr8pqA3FQ//VsLHTDvZAV4ttYOPGvYHGQq5NSalrLx5Jc3dRro/5uDOlnUMcBJg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.48.1.tgz", - "integrity": "sha512-VXO+qu2Ep6ota28ktvBm3sG53wUHS2n7bgLWmce5jTskdlCD0/JrV4tnBm1l7qpla1CeoQb8D7ShFhad+UoSOw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.52.1.tgz", + "integrity": "sha512-qCDoZfx5MpX7XQzvQ3bC4tSEMkQWQMaF/ABtLuoze03Y/flR563CCSws02qIJ23oX7lxl92LsilZjINVyTdtLw==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.48.1.tgz", - "integrity": "sha512-zl+Qyb0nLg+Y5YvKp1Ij+u9OaPaKg2/EPzTwKNiVyOHnQJlFxmXyUZL1EInczAZsEY8hVpPCLtNfhMhfxluXKQ==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.52.1.tgz", + "integrity": "sha512-hnGs0/lsFJ2PWDxNBz7pxreXo/Xz7gxYRcfePBUjsH26ad0kU/sgnVZd9LwWBpsQv65z2jlb5dkyaB9WE9M9FQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.48.1.tgz", - "integrity": "sha512-r89Qf9Oo9mKWQXumRu/1LtvVJAmEDpn8mHZMc485pRfQUMAwSSrsnaw1tQ3sszqzEgAr1c7rw6fjBI+zrAXTOw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.52.1.tgz", + "integrity": "sha512-2VxxNc/uBysyKvGeBdSM5n9eIDKH8kWD7wd9/yqbJAiVwU4Yv6tU1LSJusHKrXV/aCu1KW7t9Gug9QyeEmtn/Q==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.48.1.tgz", - "integrity": "sha512-TPKNPKfghKG/bMSc7mQYD9HxHRUkBZA4q1PEmHgICaSeHQscGqL4wBrKkhfPlDV1uYBKW02pbFMUhsOt7p4ZpA==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.52.1.tgz", + "integrity": "sha512-O6mPtsw3xEfNOe6gWFpYLeAZAIljNa4Hgna3bq15PwyN7nbjTY0wXJFRbzs/0YVf75Br+SbOQUmjKxXYjDiSiQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", - "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.52.1.tgz", + "integrity": "sha512-gA8oJOV1LnQQkDf91iebNnFInHuW0gRPEgLSOQ7EfipCEjYTHm5swm1DlH9H5RaRw4RrHuzHBegnlzc0MAstcg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" @@ -187,81 +187,81 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.48.1.tgz", - "integrity": "sha512-/RFq3TqtXDUUawwic/A9xylA2P3LDMO8dNhphHAUOU51b1ZLHrmZ6YYJm3df1APz7xLY1aht6okCQf+/vmrV9w==", + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.52.1.tgz", + "integrity": "sha512-U9zZfc5xIu9wRxZkt+HceJUAD4VKHKbAyLSloJdEyMRmphXeibfrY9cxqIXBcmPeZzGhn3Imb35Dq8l19PkJhw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.48.1.tgz", - "integrity": "sha512-Of0jTeAZRyRhC7XzDSjJef0aBkgRcvRAaw0ooYRlOw57APii7lZdq+layuNdeL72BRq1snaJhoMMwkmLIpJScw==", + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.52.1.tgz", + "integrity": "sha512-a3SGNceHmkQfq77iG8Ka+w1pvwfZa/0lzEIgse30fL0kD+yKnd/dg0dQvSfFPAEt2f21DMcGkDSSeJlO3KdQjQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.48.1.tgz", - "integrity": "sha512-bE7JcpFXzxF5zHwj/vkl2eiCBvyR1zQ7aoUdO+GDXxGp0DGw7nI0p8Xj6u8VmRQ+RDuPcICFQcCwRIJT5tDJFw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.52.1.tgz", + "integrity": "sha512-z98QEguCFDpxb4S/PyrUK1igqF8tPsdbqOUUO6ON91vJ58w+Gwa6ncrI0oNXSFcrkxA5EqPKPQ2A1PBCn08TYQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.48.1.tgz", - "integrity": "sha512-MK3wZ2koLDnvH/AmqIF1EKbJlhRS5j74OZGkLpxI4rYvNi9Jn/C7vb5DytBnQ4KUWts7QsmbdwHkxY5txQHXVw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.52.1.tgz", + "integrity": "sha512-CI7+/0I11QeZM59Uc8whd2or0kqzFVjpaPn9Qpwll/krHcBAxk24WkAQ6WX+IwDVMfpont4YGbKwAmCre3vE8Q==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1" + "@algolia/client-common": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.48.1.tgz", - "integrity": "sha512-2oDT43Y5HWRSIQMPQI4tA/W+TN/N2tjggZCUsqQV440kxzzoPGsvv9QP1GhQ4CoDa+yn6ygUsGp6Dr+a9sPPSg==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.52.1.tgz", + "integrity": "sha512-S6bDuw9byfOvm3T71cgdoZgrgnZq6hpdMLkx52Louh57nUAmvGQESz2aojOynQHjbTiV55smvAFbgn0qT4tJrg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1" + "@algolia/client-common": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.48.1.tgz", - "integrity": "sha512-xcaCqbhupVWhuBP1nwbk1XNvwrGljozutEiLx06mvqDf3o8cHyEgQSHS4fKJM+UAggaWVnnFW+Nne5aQ8SUJXg==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.52.1.tgz", + "integrity": "sha512-tqZXM+54rWo4mk5jL5Z/flE11nPmNEdXwFBM5py9DkOmbjeCNemfVd45FyM97XdzfZ0dl9uOJC6PYn1FpkeyQg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.48.1" + "@algolia/client-common": "5.52.1" }, "engines": { "node": ">= 14.0.0" @@ -3318,9 +3318,9 @@ } }, "node_modules/@docsearch/core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.5.4.tgz", - "integrity": "sha512-DbkfZbJyYAPFJtF71eAFOTQSy5z5c/hdSN0UrErORKDwXKLTJBR0c+5WxE5l+IKZx4xIaEa8RkrL7T28DTCOYw==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.3.tgz", + "integrity": "sha512-rUOujwIpxJRgD7+kicVsI3D5sqBvdiRTquzWBpTEXZs8ZXfGbfzpus5HqumaNYTppN2HvH8E2yNuRwYdHJeOlA==", "license": "MIT", "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", @@ -3340,20 +3340,20 @@ } }, "node_modules/@docsearch/css": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.5.4.tgz", - "integrity": "sha512-gzO4DJwyM9c4YEPHwaLV1nUCDC2N6yoh0QJj44dce2rcfN71mB+jpu3+F+Y/KMDF1EKV0C3m54leSWsraE94xg==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.3.tgz", + "integrity": "sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ==", "license": "MIT" }, "node_modules/@docsearch/react": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.5.4.tgz", - "integrity": "sha512-iBNFfvWoUFRUJmGQ/r+0AEp2OJgJMoYIKRiRcTDON0hObBRSLlrv2ktb7w3nc1MeNm1JIpbPA99i59TiIR49fA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.3.tgz", + "integrity": "sha512-Bg2wdDsoQVlNCcEKuEJAU04tvHCqgx8rIu+uIoM4pRtcx3TBKJuXutJik3LTA8LRc9YEyHkrYUrmcC0D7BYf+g==", "license": "MIT", "dependencies": { "@algolia/autocomplete-core": "1.19.2", - "@docsearch/core": "4.5.4", - "@docsearch/css": "4.5.4" + "@docsearch/core": "4.6.3", + "@docsearch/css": "4.6.3" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", @@ -3376,6 +3376,38 @@ } } }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-core": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", + "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", + "@algolia/autocomplete-shared": "1.19.2" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", + "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.19.2" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-shared": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", + "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, "node_modules/@docusaurus/babel": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", @@ -3662,12 +3694,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz", - "integrity": "sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.1.tgz", + "integrity": "sha512-YoOZKUdGlp8xSYhuAkGdSo5Ydkbq4V4eK3sD8v0a2hloxCWdQbNBhkc+Ko9QyjpESc0BYcIGM5iHVAy5hdFV6w==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.2", + "@docusaurus/types": "3.10.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3680,6 +3712,28 @@ "react-dom": "*" } }, + "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/plugin-client-redirects": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.9.2.tgz", @@ -3705,20 +3759,21 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz", - "integrity": "sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", + "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "cheerio": "1.0.0-rc.12", + "combine-promises": "^1.1.0", "feed": "^4.2.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21", @@ -3738,129 +3793,213 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", - "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@types/react-router-config": "^5.0.7", - "combine-promises": "^1.1.0", + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "schema-dts": "^1.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", "tslib": "^2.6.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" }, "engines": { "node": ">=20.0" }, "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } } }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz", - "integrity": "sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", "tslib": "^2.6.0", - "webpack": "^5.88.1" + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" }, "engines": { "node": ">=20.0" }, "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } } }, - "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz", - "integrity": "sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "tslib": "^2.6.0" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" }, "engines": { - "node": ">=20.0" + "node": ">=18.0.0" } }, - "node_modules/@docusaurus/plugin-debug": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz", - "integrity": "sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "fs-extra": "^11.1.1", - "react-json-view-lite": "^2.3.0", + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz", - "integrity": "sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz", - "integrity": "sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@types/gtag.js": "^0.0.12", - "tslib": "^2.6.0" + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" @@ -3870,16 +4009,4906 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz", - "integrity": "sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw==", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "tslib": "^2.6.0" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", + "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "schema-dts": "^1.1.2", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.1.tgz", + "integrity": "sha512-huJpaRPMl42nsFwuCXvV8bVDj2MazuwRJIUylI/RSlmZeJssVoZXeCjVf1y+1Drtpa9SKcdGn8yoJ76IRJijtw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", + "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", + "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^2.3.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", + "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", + "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@types/gtag.js": "^0.0.20", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", + "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-ideal-image": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.2.tgz", + "integrity": "sha512-YYYbmC2wSYFd7o4//5rPXt9+DkZwfwjCUmyGi5OIVqEbwELK80o3COXs2Xd0BtVIpuRvG7pKCYrMQwVo32Y9qw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/lqip-loader": "3.9.2", + "@docusaurus/responsive-loader": "^1.7.0", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", + "sharp": "^0.32.3", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "jimp": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "jimp": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", + "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-svgr": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", + "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-svgr/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.10.1.tgz", + "integrity": "sha512-YO/FL8v1zmbxoTso6mjMz/RDjhaTJxb1UpFFTDdY5847LLDCeyYiYlrhyTbgN1RIN3xnkLKZ9Lj1x8hUzI4JOg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/plugin-css-cascade-layers": "3.10.1", + "@docusaurus/plugin-debug": "3.10.1", + "@docusaurus/plugin-google-analytics": "3.10.1", + "@docusaurus/plugin-google-gtag": "3.10.1", + "@docusaurus/plugin-google-tag-manager": "3.10.1", + "@docusaurus/plugin-sitemap": "3.10.1", + "@docusaurus/plugin-svgr": "3.10.1", + "@docusaurus/theme-classic": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-search-algolia": "3.10.1", + "@docusaurus/types": "3.10.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/responsive-loader": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz", + "integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==", + "dependencies": { + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "jimp": "*", + "sharp": "*" + }, + "peerDependenciesMeta": { + "jimp": { + "optional": true + }, + "sharp": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", + "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.45", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.5.4", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/theme-translations": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", + "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.1.tgz", + "integrity": "sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==", + "license": "MIT", + "dependencies": { + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.1.tgz", + "integrity": "sha512-OTaARARVZj2GvkJQjB+1jOIxntRaXea+G+fMsNqrZBAU1O1vJKDW22R7kECOHW27oJCLFN9HKaZeRrfAUyviug==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "^1.19.2", + "@docsearch/react": "^3.9.0 || ^4.3.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "algoliasearch": "^5.37.0", + "algoliasearch-helper": "^3.26.0", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" @@ -3889,255 +8918,193 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.2.tgz", - "integrity": "sha512-YYYbmC2wSYFd7o4//5rPXt9+DkZwfwjCUmyGi5OIVqEbwELK80o3COXs2Xd0BtVIpuRvG7pKCYrMQwVo32Y9qw==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/theme-translations": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", + "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/lqip-loader": "3.9.2", - "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "sharp": "^0.32.3", - "tslib": "^2.6.0", - "webpack": "^5.88.1" + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" }, "peerDependencies": { - "jimp": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "jimp": { - "optional": true - } } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", - "hasInstallScript": true, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/types/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" }, "engines": { - "node": ">=14.15.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=10.0.0" } }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz", - "integrity": "sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "sitemap": "^7.1.1", - "tslib": "^2.6.0" + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz", - "integrity": "sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@svgr/core": "8.1.0", - "@svgr/webpack": "^8.1.0", - "tslib": "^2.6.0", - "webpack": "^5.88.1" + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/preset-classic": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz", - "integrity": "sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/plugin-content-blog": "3.9.2", - "@docusaurus/plugin-content-docs": "3.9.2", - "@docusaurus/plugin-content-pages": "3.9.2", - "@docusaurus/plugin-css-cascade-layers": "3.9.2", - "@docusaurus/plugin-debug": "3.9.2", - "@docusaurus/plugin-google-analytics": "3.9.2", - "@docusaurus/plugin-google-gtag": "3.9.2", - "@docusaurus/plugin-google-tag-manager": "3.9.2", - "@docusaurus/plugin-sitemap": "3.9.2", - "@docusaurus/plugin-svgr": "3.9.2", - "@docusaurus/theme-classic": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/theme-search-algolia": "3.9.2", - "@docusaurus/types": "3.9.2" + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/responsive-loader": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz", - "integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", "dependencies": { - "loader-utils": "^2.0.0" + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=12" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "jimp": "*", - "sharp": "*" + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "jimp": { + "@rspack/core": { "optional": true }, - "sharp": { + "webpack": { "optional": true } } }, - "node_modules/@docusaurus/theme-classic": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz", - "integrity": "sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/plugin-content-blog": "3.9.2", - "@docusaurus/plugin-content-docs": "3.9.2", - "@docusaurus/plugin-content-pages": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "infima": "0.2.0-alpha.45", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.5.4", - "prism-react-renderer": "^2.3.0", - "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", - "rtlcss": "^4.1.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" }, "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "node": ">=18.0.0" } }, - "node_modules/@docusaurus/theme-common": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.2.tgz", - "integrity": "sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag==", + "node_modules/@docusaurus/theme-search-algolia/node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "clsx": "^2.0.0", - "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^2.3.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" }, "engines": { - "node": ">=20.0" + "node": ">=14.21.3" }, "peerDependencies": { - "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz", - "integrity": "sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw==", - "license": "MIT", - "dependencies": { - "@docsearch/react": "^3.9.0 || ^4.1.0", - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/plugin-content-docs": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "algoliasearch": "^5.37.0", - "algoliasearch-helper": "^3.26.0", - "clsx": "^2.0.0", - "eta": "^2.2.0", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=20.0" + "@rspack/core": "*", + "webpack": "3 || 4 || 5" }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/@docusaurus/theme-translations": { @@ -5370,9 +10337,9 @@ } }, "node_modules/@types/gtag.js": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.20.tgz", + "integrity": "sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg==", "license": "MIT" }, "node_modules/@types/hast": { @@ -5970,34 +10937,34 @@ } }, "node_modules/algoliasearch": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", - "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", - "license": "MIT", - "dependencies": { - "@algolia/abtesting": "1.14.1", - "@algolia/client-abtesting": "5.48.1", - "@algolia/client-analytics": "5.48.1", - "@algolia/client-common": "5.48.1", - "@algolia/client-insights": "5.48.1", - "@algolia/client-personalization": "5.48.1", - "@algolia/client-query-suggestions": "5.48.1", - "@algolia/client-search": "5.48.1", - "@algolia/ingestion": "1.48.1", - "@algolia/monitoring": "1.48.1", - "@algolia/recommend": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.52.1.tgz", + "integrity": "sha512-fHA8+kXTbjagw3jkLiaS7KKrH8qe2DyOsiUhGlN4cdT77PEsfqXZl7ewDk1hsg+pJnPlnE50XtLxjR91iJOpmg==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.18.1", + "@algolia/client-abtesting": "5.52.1", + "@algolia/client-analytics": "5.52.1", + "@algolia/client-common": "5.52.1", + "@algolia/client-insights": "5.52.1", + "@algolia/client-personalization": "5.52.1", + "@algolia/client-query-suggestions": "5.52.1", + "@algolia/client-search": "5.52.1", + "@algolia/ingestion": "1.52.1", + "@algolia/monitoring": "1.52.1", + "@algolia/recommend": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.27.1.tgz", - "integrity": "sha512-XXGr02Cz285vLbqM6vPfb39xqV1ptpFr1xn9mqaW+nUvYTvFTdKgYTC/Cg1VzgRTQqNkq9+LlUVv8cfCeOoKig==", + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.29.1.tgz", + "integrity": "sha512-6ck2YFudF2Pje7szQoPBiRFTGfd+1I+0I/WfLPGn0bj1kvrFoOQmNyedNiDxTk3/r4IfSLDYk+RA4G7u8H6+yA==", "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" @@ -6093,6 +11060,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -7327,6 +12303,18 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz", + "integrity": "sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/copy-webpack-plugin": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", @@ -16134,9 +21122,10 @@ } }, "node_modules/react-loadable-ssr-addon-v5-slorber": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz", + "integrity": "sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.3" }, @@ -17520,9 +22509,9 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "node_modules/sitemap": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", - "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.3.tgz", + "integrity": "sha512-tAjEd+wt/YwnEbfNB2ht51ybBJxbEWwe5ki/Z//Wh0rpBFTCUSj46GnxUKEWzhfuJTsee8x3lybHxFgUMig2hw==", "license": "MIT", "dependencies": { "@types/node": "^17.0.5", diff --git a/site/package.json b/site/package.json index 279aa24ccd..82711db41e 100644 --- a/site/package.json +++ b/site/package.json @@ -17,7 +17,7 @@ "@docusaurus/core": "^3.9.2", "@docusaurus/plugin-client-redirects": "^3.9.2", "@docusaurus/plugin-ideal-image": "^3.9.2", - "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", "@types/react": "^18.3.28", "clsx": "^2.1.1", From 981b5420deb122155312f1bdeb1ab687a78e8b5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 15:21:06 -0400 Subject: [PATCH 399/448] deps: bump react-dom from 18.3.1 to 19.2.5 in /site (#2339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) from 18.3.1 to 19.2.5.
Release notes

Sourced from react-dom's releases.

19.2.5 (April 8th, 2026)

React Server Components

19.2.4 (January 26th, 2026)

React Server Components

19.2.3 (December 11th, 2025)

React Server Components

19.2.2 (December 11th, 2025)

React Server Components

19.2.1 (December 3rd, 2025)

React Server Components

19.2.0 (Oct 1, 2025)

Below is a list of all new features, APIs, and bug fixes.

Read the React 19.2 release post for more information.

New React Features

  • <Activity>: A new API to hide and restore the UI and internal state of its children.
  • useEffectEvent is a React Hook that lets you extract non-reactive logic into an Effect Event.
  • cacheSignal (for RSCs) lets your know when the cache() lifetime is over.
  • React Performance tracks appear on the Performance panel’s timeline in your browser developer tools

New React DOM Features

  • Added resume APIs for partial pre-rendering with Web Streams:
  • Added resume APIs for partial pre-rendering with Node Streams:
  • Updated prerender APIs to return a postponed state that can be passed to the resume APIs.

Notable changes

  • React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming <ViewTransition> Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.

... (truncated)

Changelog

Sourced from react-dom's changelog.

19.2.1 (Dec 3, 2025)

React Server Components

19.2.0 (October 1st, 2025)

Below is a list of all new features, APIs, and bug fixes.

Read the React 19.2 release post for more information.

New React Features

  • <Activity>: A new API to hide and restore the UI and internal state of its children.
  • useEffectEvent is a React Hook that lets you extract non-reactive logic into an Effect Event.
  • cacheSignal (for RSCs) lets your know when the cache() lifetime is over.
  • React Performance tracks appear on the Performance panel’s timeline in your browser developer tools

New React DOM Features

  • Added resume APIs for partial pre-rendering with Web Streams:
  • Added resume APIs for partial pre-rendering with Node Streams:
  • Updated prerender APIs to return a postponed state that can be passed to the resume APIs.

Notable changes

  • React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming <ViewTransition> Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.
  • Add Node Web Streams (prerender, renderToReadableStream) to server-side-rendering APIs for Node.js
  • Use underscore instead of : IDs generated by useId

All Changes

React

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-dom&package-manager=npm_and_yarn&previous-version=18.3.1&new-version=19.2.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 41 +++++++++++++++++++++-------------------- site/package.json | 2 +- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index a1eb316bc1..7e405a5cdc 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -19,7 +19,7 @@ "micromatch": "^4.0.8", "prism-react-renderer": "^2.4.1", "react": "^18.3.1", - "react-dom": "^18.3.1", + "react-dom": "^19.2.5", "sharp": "^0.33.5" }, "devDependencies": { @@ -15441,6 +15441,7 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" } @@ -21058,27 +21059,29 @@ } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.2.5" } }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" }, "node_modules/react-helmet-async": { + "name": "@slorber/react-helmet-async", "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", - "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "resolved": "https://registry.npmjs.org/@slorber/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-e9/OK8VhwUSc67diWI8Rb3I0YgI9/SBQtnhe9aEuK6MhZm7ntZZimXgwXnd8W96YTmSOb9M4d8LwhRZyhWr/1A==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.12.5", "invariant": "^2.2.4", @@ -21087,8 +21090,8 @@ "shallowequal": "^1.1.0" }, "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + "react": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/react-is": { @@ -21971,13 +21974,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" }, "node_modules/schema-dts": { "version": "1.1.5", @@ -22285,7 +22285,8 @@ "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" }, "node_modules/sharp": { "version": "0.33.5", diff --git a/site/package.json b/site/package.json index 82711db41e..04c1bebdd6 100644 --- a/site/package.json +++ b/site/package.json @@ -25,7 +25,7 @@ "micromatch": "^4.0.8", "prism-react-renderer": "^2.4.1", "react": "^18.3.1", - "react-dom": "^18.3.1", + "react-dom": "^19.2.5", "sharp": "^0.33.5" }, "devDependencies": { From a78b147fd176568bfaa61581f30e78145ad7bdef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 15:21:07 -0400 Subject: [PATCH 400/448] deps: bump typescript from 5.9.3 to 6.0.2 in /site (#2342) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.2.
Release notes

Sourced from typescript's releases.

TypeScript 6.0

For release notes, check out the release announcement blog post.

Downloads are available on:

TypeScript 6.0 Beta

For release notes, check out the release announcement.

Downloads are available on:

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typescript&package-manager=npm_and_yarn&previous-version=5.9.3&new-version=6.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 8 ++++---- site/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 7e405a5cdc..a49fc1cdb5 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -28,7 +28,7 @@ "@docusaurus/types": "^3.9.2", "css-loader": "^7.1.2", "style-loader": "^4.0.0", - "typescript": "^5.7.3" + "typescript": "^6.0.2" }, "engines": { "node": ">=18.0.0" @@ -23300,9 +23300,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "devOptional": true, "license": "Apache-2.0", "bin": { diff --git a/site/package.json b/site/package.json index 04c1bebdd6..deae026f21 100644 --- a/site/package.json +++ b/site/package.json @@ -34,7 +34,7 @@ "@docusaurus/types": "^3.9.2", "css-loader": "^7.1.2", "style-loader": "^4.0.0", - "typescript": "^5.7.3" + "typescript": "^6.0.2" }, "browserslist": { "production": [ From 1fdc1be7d38cef56b5bbecf2566af0013700d6e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 19:48:45 +0000 Subject: [PATCH 401/448] deps: bump windows/servercore in /controller (#2343) Bumps windows/servercore in `/controller` from `e000e9a` to `86da395`. Updates `windows/servercore` from `e000e9a` to `86da395` Updates `windows/servercore` from `e000e9a` to `86da395` Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile.windows-2022 | 2 +- controller/Dockerfile.windows-retina-oss-build | 2 +- hack/tools/kapinger/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/controller/Dockerfile.windows-2022 b/controller/Dockerfile.windows-2022 index fc9aa2c5c7..4872556a03 100644 --- a/controller/Dockerfile.windows-2022 +++ b/controller/Dockerfile.windows-2022 @@ -1,6 +1,6 @@ # pinned base image # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:e000e9a1712065a0218447c20ae19984b447fa741d11cf64696b8a1172fcd7da AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:86da395cfd2b35dbfc2e9d08719550c51b0570c394bff8f92622a19234766185 AS ltsc2022 FROM ltsc2022 AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/controller/Dockerfile.windows-retina-oss-build b/controller/Dockerfile.windows-retina-oss-build index ab4b5d8b84..a6c6346883 100644 --- a/controller/Dockerfile.windows-retina-oss-build +++ b/controller/Dockerfile.windows-retina-oss-build @@ -3,7 +3,7 @@ ARG OS_VERSION=ltsc2022 # pinned base images # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:e000e9a1712065a0218447c20ae19984b447fa741d11cf64696b8a1172fcd7da AS ltsc2022 +FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:86da395cfd2b35dbfc2e9d08719550c51b0570c394bff8f92622a19234766185 AS ltsc2022 FROM ${OS_VERSION} AS agent-win ARG GOARCH=amd64 # default to amd64 diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index 738c66f92c..c530d9e06b 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -25,7 +25,7 @@ RUN go mod download RUN GOOS=windows go build -o kapinger.exe . # skopeo inspect docker://mcr.microsoft.com/windows/servercore:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:e000e9a1712065a0218447c20ae19984b447fa741d11cf64696b8a1172fcd7da AS windows +FROM mcr.microsoft.com/windows/servercore:ltsc2022@sha256:86da395cfd2b35dbfc2e9d08719550c51b0570c394bff8f92622a19234766185 AS windows WORKDIR /app COPY --from=windows-builder /build/kapinger.exe . ENTRYPOINT [ "cmd.exe" ] From 220a1ae19ba99616ca4c323f2c49408056ed5848 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 19:49:00 +0000 Subject: [PATCH 402/448] deps: bump windows/nanoserver in /controller (#2344) Bumps windows/nanoserver in `/controller` from `3680dad` to `3ca7daa`. Updates `windows/nanoserver` from `3680dad` to `3ca7daa` Updates `windows/nanoserver` from `3680dad` to `3ca7daa` Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- controller/Dockerfile.windows-native | 2 +- operator/Dockerfile.windows-2022 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 9a6d4c22fd..fc06fc38c7 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -24,7 +24,7 @@ FROM --platform=windows/amd64 ${BUILDER_IMAGE} as pktmon-builder WORKDIR C:\\retina # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver:ltsc2022@sha256:3680dad0bb773da8efcd9d928eaf4e33817875ab71a43792640ab1bcc0b3c074 AS final +FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver:ltsc2022@sha256:3ca7daac9e971bd440920e408a29d46545b717775794c71561d57ac2f9354a48 AS final ADD https://github.com/microsoft/etl2pcapng/releases/download/v1.10.0/etl2pcapng.exe /etl2pcapng.exe SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue';"] COPY --from=builder C:\\retina\\windows\\kubeconfigtemplate.yaml kubeconfigtemplate.yaml diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 8cbf5c7379..92e87f37a7 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -16,7 +16,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -ldflags "-X g # Copy into final image # skopeo inspect docker://mcr.microsoft.com/windows/nanoserver:ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/windows/nanoserver:ltsc2022@sha256:3680dad0bb773da8efcd9d928eaf4e33817875ab71a43792640ab1bcc0b3c074 +FROM mcr.microsoft.com/windows/nanoserver:ltsc2022@sha256:3ca7daac9e971bd440920e408a29d46545b717775794c71561d57ac2f9354a48 COPY --from=builder /usr/src/retina/windows/kubeconfigtemplate.yaml kubeconfigtemplate.yaml COPY --from=builder /usr/src/retina/windows/setkubeconfigpath.ps1 setkubeconfigpath.ps1 From 8cf0c245791c193dc91987d9452f49b1f1111350 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Wed, 13 May 2026 21:33:54 +0100 Subject: [PATCH 403/448] fix: --node-names should clear default kubernetes.io/os=linux node-selector (#2303) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description When using `--node-names` to target specific nodes (e.g., Windows nodes), the default `--node-selectors=kubernetes.io/os=linux` was not being cleared. This caused the resulting `NodeSelector` to include both the hostname `MatchExpression` and the `kubernetes.io/os=linux` `MatchLabel`, filtering out all Windows nodes and producing a `no targets are selected` error. This PR adds `opts.nodeNames` to the condition that clears the default node-selector, so `--node-names` can target nodes of any OS. ## Related Issue N/A — discovered during manual testing of capture targeting on mixed-OS clusters. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed **Before fix:** `$ kubectl retina capture create --node-names "aksnwin22000000" --host-path /mnt/retina/captures --duration 30s Error: no targets are selected by node selector, pod selector, or pod names` **After fix:** Capture jobs are created successfully for the specified Windows node. **Tests added:** - TestNodeNamesClearsDefaultNodeSelector — 3 cases: Windows-only, Linux-only, and mixed-OS node targeting via --node-names, verifying jobs are created with correct node affinity. - NewWindowsNode() helper and updated NewNode() to include kubernetes.io/os labels. ## Tests Cluster nodes with linux and windows nodes image Before changes - targeting the windows node with name `aksnwin22000000` does not find any targets as it doesn't clear the default target of `--node-selectors=kubernetes.io/os=linux` image After changes - targeting the windows node with the name `aksnwin22000000` creates a capture targeting that node image ## Additional Notes **Changes:** - create.go: Added opts.nodeNames != "" to the condition at line 309 that clears the default node-selector. - create_test.go: Added TestNodeNamesClearsDefaultNodeSelector with NewWindowsNode helper. - 02-cli.md: Updated node-names and node-selectors flag descriptions to document the override behavior. --- cli/cmd/capture/create.go | 7 +- cli/cmd/capture/create_test.go | 112 +++++++++++++++++++++++++++++++ cli/cmd/capture/download_test.go | 1 + docs/04-Captures/02-cli.md | 4 +- 4 files changed, 119 insertions(+), 5 deletions(-) diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index 0669abb7ed..a18efcfbfe 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -306,10 +306,11 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti capture.Spec.CaptureConfiguration.CaptureOption.Duration = &metav1.Duration{Duration: opts.duration} } - if opts.namespaceSelectors != "" || opts.podSelectors != "" || opts.podNames != "" { - // if node selector is using the default value (aka hasn't been set by user), set it to nil to prevent clash with namespace and pod selector + if opts.namespaceSelectors != "" || opts.podSelectors != "" || opts.podNames != "" || opts.nodeNames != "" { + // if node selector is using the default value (aka hasn't been set by user), set it to nil to prevent clash + // with namespace/pod selectors, pod names, or explicit node names if opts.nodeSelectors == DefaultNodeSelectors { - retinacmd.Logger.Info("Overriding default node selectors value and setting it to nil. Using namespace, pod selectors, or pod names. " + + retinacmd.Logger.Info("Overriding default node selectors value and setting it to nil. Using namespace, pod selectors, pod names, or node names. " + "To use node selector, please remove namespace and pod selectors.") opts.nodeSelectors = "" } diff --git a/cli/cmd/capture/create_test.go b/cli/cmd/capture/create_test.go index e2d3906586..74a7e10810 100644 --- a/cli/cmd/capture/create_test.go +++ b/cli/cmd/capture/create_test.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "math/rand" + "strings" "testing" retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" @@ -66,6 +67,7 @@ func NewNode(name string) *corev1.Node { Name: name, Labels: map[string]string{ "kubernetes.io/hostname": name, + "kubernetes.io/os": "linux", }, }, } @@ -510,3 +512,113 @@ func TestCaptureTarget_PodNames_MutualExclusivity(t *testing.T) { }) } } + +func TestNodeNamesClearsDefaultNodeSelector(t *testing.T) { + // When --node-names is specified, the default kubernetes.io/os=linux node-selector + // must be cleared so that Windows nodes can be targeted by name. + winNode := NewWindowsNode("win-node-1") + linNode := NewNode("lin-node-1") + + kubeClient := fake.NewClientset(winNode, linNode) + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction, ok := action.(clienttesting.CreateAction) + if !ok { + return false, nil, fmt.Errorf("expected CreateAction, got %T", action) //nolint:err113 // test code + } + job := createAction.GetObject().(*batchv1.Job) + if job.Name == "" { + job.Name = job.GenerateName + randomString(5) + } + return false, job, nil + }) + + cases := []struct { + name string + args []string + wantNodes []string + wantErr bool + }{ + { + name: "node-names targets a Windows node without explicit node-selectors", + args: []string{ + "create", + "--name=test-win", + "--namespace=default", + "--node-names=win-node-1", + "--duration=10s", + "--host-path=/tmp/capture", + }, + wantNodes: []string{"win-node-1"}, + wantErr: false, + }, + { + name: "node-names targets a Linux node without explicit node-selectors", + args: []string{ + "create", + "--name=test-lin", + "--namespace=default", + "--node-names=lin-node-1", + "--duration=10s", + "--host-path=/tmp/capture", + }, + wantNodes: []string{"lin-node-1"}, + wantErr: false, + }, + { + name: "node-names targets both Linux and Windows nodes", + args: []string{ + "create", + "--name=test-both", + "--namespace=default", + "--node-names=lin-node-1,win-node-1", + "--duration=10s", + "--host-path=/tmp/capture", + }, + wantNodes: []string{"lin-node-1", "win-node-1"}, + wantErr: false, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + cmd := NewCommand(kubeClient) + cmd.SetArgs(tc.args) + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + err := cmd.Execute() + + if tc.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err, "capture create should succeed for node-names targeting %v", tc.wantNodes) + + // Verify jobs were created for the expected nodes + jobs, err := kubeClient.BatchV1().Jobs("default").List(context.TODO(), metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", label.CaptureNameLabel, strings.TrimPrefix(tc.args[1], "--name=")), + }) + require.NoError(t, err) + require.Len(t, jobs.Items, len(tc.wantNodes), "should create one job per target node") + + gotNodes := map[string]bool{} + for _, job := range jobs.Items { + nodeAffinity := job.Spec.Template.Spec.Affinity.NodeAffinity + require.NotNil(t, nodeAffinity) + for _, term := range nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + for _, expr := range term.MatchExpressions { + if expr.Key == "kubernetes.io/hostname" { + for _, v := range expr.Values { + gotNodes[v] = true + } + } + } + } + } + + for _, wantNode := range tc.wantNodes { + require.True(t, gotNodes[wantNode], "expected job targeting node %s", wantNode) + } + }) + } +} diff --git a/cli/cmd/capture/download_test.go b/cli/cmd/capture/download_test.go index 1609d60796..25ae298f07 100644 --- a/cli/cmd/capture/download_test.go +++ b/cli/cmd/capture/download_test.go @@ -52,6 +52,7 @@ func NewWindowsNode(name string) *corev1.Node { Name: name, Labels: map[string]string{ "kubernetes.io/hostname": name, + "kubernetes.io/os": "windows", }, }, Status: corev1.NodeStatus{ diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index dd42ad59be..6d07e625fa 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -71,8 +71,8 @@ The network traffic will be uploaded to the specified output location. | `name` | string | retina-capture | A name for the Retina Capture. | | | `namespace` | string | default | Sets the namespace which hosts the capture job and the other Kubernetes resources for a network capture. | Ensure the namespace exists. | | `namespace-selectors` | string | "" | Capture network captures on pods filtered by the provided namespace selectors. | Pair with `pod-selectors`. | -| `node-names` | string | "" | A comma-separated list of node names to select nodes on which the network capture will be performed. | | -| `node-selectors` | string | kubernetes.io/os=linux | A comma-separated list of node labels to select nodes on which the network capture will be performed. | | +| `node-names` | string | "" | A comma-separated list of node names to select nodes on which the network capture will be performed. | Overrides the default `node-selectors` value, allowing captures on nodes of any OS (including Windows). | +| `node-selectors` | string | kubernetes.io/os=linux | A comma-separated list of node labels to select nodes on which the network capture will be performed. | Cleared automatically when `node-names`, `pod-selectors`, `pod-names`, or `namespace-selectors` are specified. | | `no-wait` | bool | true | By default, Retina capture CLI will exit before the jobs are completed. If false, the CLI will wait until the jobs are completed and clean up the Kubernetes resources created. | | | `packet-size` | int | 0 | Limit the packet size in bytes. Packets longer than the defined maximum size will be truncated. The default value 0 indicates no limit. This is beneficial when the user wants to reduce the capture file size or hide customer data due to security concerns. | Only works on Linux. | | `pod-names` | string | "" | A comma-separated list of specific pod names to select pods on which the network capture will be performed. | Mutually exclusive with `node-selectors`, `pod-selectors`, and `namespace-selectors`. | From 895b84270499f63976e7ef91935b21439f513aae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 18:01:46 -0400 Subject: [PATCH 404/448] deps: bump @docusaurus/types from 3.9.2 to 3.10.1 in /site (#2345) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@docusaurus/types](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-types) from 3.9.2 to 3.10.1.
Release notes

Sourced from @​docusaurus/types's releases.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Changelog

Sourced from @​docusaurus/types's changelog.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Commits
  • 41c1a45 v3.10.1
  • 4892e7f feat(core): add future.v4.mdx1CompatDisabledByDefault flag (#11896)
  • 1451780 chore(ci): fixes for the npm trusted publishing workflow (#11823)
  • 5dff744 chore(ci): add Trusted Publishing release workflow through dispatch action (#...
  • 29c3b5c feat(core): Docusaurus Faster is stable + v4 future flag turns it on by defau...
  • 2a7f8b9 feat(core): promote siteConfig.storage to stable + add `future.v4.siteStora...
  • c6a86ff feat(core): support custom html elements in head tags (#11571)
  • acc66c1 feat(core): New siteConfig future.experimental_vcs API + `future.experimen...
  • bca9ce7 chore: release v3.9.2 (#11491)
  • See full diff in compare view
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​docusaurus/types since your current version.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 440 +++++++++-------------------------------- site/package.json | 2 +- 2 files changed, 93 insertions(+), 349 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index a49fc1cdb5..2868326a04 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -25,7 +25,7 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.9.2", - "@docusaurus/types": "^3.9.2", + "@docusaurus/types": "^3.10.1", "css-loader": "^7.1.2", "style-loader": "^4.0.0", "typescript": "^6.0.2" @@ -3477,6 +3477,28 @@ } } }, + "node_modules/@docusaurus/bundler/node_modules/@docusaurus/types": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/bundler/node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -3712,28 +3734,6 @@ "react-dom": "*" } }, - "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-client-redirects": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.9.2.tgz", @@ -4009,28 +4009,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -4406,28 +4384,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -4793,28 +4749,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -5173,28 +5107,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -5558,28 +5470,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -5941,28 +5831,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -6325,28 +6193,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -6708,28 +6554,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -6886,6 +6710,28 @@ } } }, + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/types": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { "version": "0.32.6", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", @@ -7148,28 +6994,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -7535,28 +7359,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -7929,28 +7731,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -8370,28 +8150,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -8598,28 +8356,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -8931,42 +8667,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", - "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/types/node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -9128,9 +8828,9 @@ "license": "MIT" }, "node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", @@ -9194,6 +8894,28 @@ "node": ">=20.0" } }, + "node_modules/@docusaurus/utils-common/node_modules/@docusaurus/types": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/utils-validation": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz", @@ -9213,6 +8935,28 @@ "node": ">=20.0" } }, + "node_modules/@docusaurus/utils/node_modules/@docusaurus/types": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@emnapi/runtime": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", diff --git a/site/package.json b/site/package.json index deae026f21..ecf95dd58c 100644 --- a/site/package.json +++ b/site/package.json @@ -31,7 +31,7 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.9.2", - "@docusaurus/types": "^3.9.2", + "@docusaurus/types": "^3.10.1", "css-loader": "^7.1.2", "style-loader": "^4.0.0", "typescript": "^6.0.2" From aacf7552b60a329bd8446277bfbf60a2c171af3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 23:06:27 +0000 Subject: [PATCH 405/448] deps: bump @docusaurus/tsconfig from 3.9.2 to 3.10.1 in /site (#2341) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@docusaurus/tsconfig](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-tsconfig) from 3.9.2 to 3.10.1.
Release notes

Sourced from @​docusaurus/tsconfig's releases.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Changelog

Sourced from @​docusaurus/tsconfig's changelog.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Commits
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​docusaurus/tsconfig since your current version.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 8 ++++---- site/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 2868326a04..2085e61e40 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", - "@docusaurus/tsconfig": "^3.9.2", + "@docusaurus/tsconfig": "^3.10.1", "@docusaurus/types": "^3.10.1", "css-loader": "^7.1.2", "style-loader": "^4.0.0", @@ -8821,9 +8821,9 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.9.2.tgz", - "integrity": "sha512-j6/Fp4Rlpxsc632cnRnl5HpOWeb6ZKssDj6/XzzAzVGXXfm9Eptx3rxCC+fDzySn9fHTS+CWJjPineCR1bB5WQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.10.1.tgz", + "integrity": "sha512-rYvB7yqkdqWIpAbDzQljGfM4cDBkLTbhmagZBEcsyj6oPUsz47lmW2pYdN1j+7sGFgltbAmQH62xfbrij4Eh6Q==", "dev": true, "license": "MIT" }, diff --git a/site/package.json b/site/package.json index ecf95dd58c..62b40c9da7 100644 --- a/site/package.json +++ b/site/package.json @@ -30,7 +30,7 @@ }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", - "@docusaurus/tsconfig": "^3.9.2", + "@docusaurus/tsconfig": "^3.10.1", "@docusaurus/types": "^3.10.1", "css-loader": "^7.1.2", "style-loader": "^4.0.0", From d7377df66be2598e3302be2f5fd7af1930c62556 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 20:36:58 -0400 Subject: [PATCH 406/448] deps: bump @docusaurus/core from 3.9.2 to 3.10.1 in /site (#2349) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) from 3.9.2 to 3.10.1.
Release notes

Sourced from @​docusaurus/core's releases.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Changelog

Sourced from @​docusaurus/core's changelog.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Commits
  • 41c1a45 v3.10.1
  • d4164ae chore: cherry-pick commits for v3.10.1 patch release (#11982)
  • 4892e7f feat(core): add future.v4.mdx1CompatDisabledByDefault flag (#11896)
  • 543eaeb fix(core): fix url.resolve() Node.js deprecation warning (#11844)
  • 1a52592 fix(faster): upgrade Rspack, fix Yarn PnP support (#11817)
  • 4a0273f fix(create-docusaurus): fix support for TypeScript 6.0 + fix our CI (#11843)
  • f659aef fix(core): upgrade serve handler min version to for upgrade users to a secure...
  • 1451780 chore(ci): fixes for the npm trusted publishing workflow (#11823)
  • 5dff744 chore(ci): add Trusted Publishing release workflow through dispatch action (#...
  • 29c3b5c feat(core): Docusaurus Faster is stable + v4 future flag turns it on by defau...
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​docusaurus/core since your current version.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 5060 +++++++++------------------------------- site/package.json | 2 +- 2 files changed, 1160 insertions(+), 3902 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 2085e61e40..698538e817 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -8,7 +8,7 @@ "name": "retina", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.9.2", + "@docusaurus/core": "^3.10.1", "@docusaurus/plugin-client-redirects": "^3.9.2", "@docusaurus/plugin-ideal-image": "^3.9.2", "@docusaurus/preset-classic": "^3.10.1", @@ -1927,9 +1927,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.0.tgz", - "integrity": "sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.2.tgz", + "integrity": "sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw==", "license": "MIT", "dependencies": { "core-js-pure": "^3.48.0" @@ -3409,9 +3409,9 @@ } }, "node_modules/@docusaurus/babel": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", - "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3422,10 +3422,9 @@ "@babel/preset-react": "^7.25.9", "@babel/preset-typescript": "^7.25.9", "@babel/runtime": "^7.25.9", - "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3434,18 +3433,76 @@ "node": ">=20.0" } }, + "node_modules/@docusaurus/babel/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/babel/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/babel/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, "node_modules/@docusaurus/bundler": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", - "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.9.2", - "@docusaurus/cssnano-preset": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", @@ -3463,7 +3520,7 @@ "tslib": "^2.6.0", "url-loader": "^4.1.1", "webpack": "^5.95.0", - "webpackbar": "^6.0.1" + "webpackbar": "^7.0.0" }, "engines": { "node": ">=20.0" @@ -3477,26 +3534,62 @@ } } }, - "node_modules/@docusaurus/bundler/node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "node_modules/@docusaurus/bundler/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/bundler/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" + "webpack": "^5.88.1" }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/bundler/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" } }, "node_modules/@docusaurus/bundler/node_modules/css-loader": { @@ -3535,18 +3628,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", - "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.9.2", - "@docusaurus/bundler": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3558,7 +3651,7 @@ "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", - "execa": "5.1.1", + "execa": "^5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", @@ -3569,12 +3662,12 @@ "prompts": "^2.4.2", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", "react-router": "^5.3.4", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.4", "semver": "^7.5.4", - "serve-handler": "^6.1.6", + "serve-handler": "^6.1.7", "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", @@ -3590,73 +3683,156 @@ "node": ">=20.0" }, "peerDependencies": { + "@docusaurus/faster": "*", "@mdx-js/react": "^3.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } } }, - "node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "node_modules/@docusaurus/core/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" + "chalk": "^4.1.2", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0" } }, - "node_modules/@docusaurus/cssnano-preset": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", - "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", + "node_modules/@docusaurus/core/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/logger": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", - "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", + "node_modules/@docusaurus/core/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/lqip-loader": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.9.2.tgz", - "integrity": "sha512-Q9QO0E+HLKhcpKVOIXRVBdJ1bbxxpfSwBll5NsmGxcx1fArH0fFi68cpEztqBg7WwbFRb976MTlqlBuGrMLpuw==", + "node_modules/@docusaurus/core/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "file-loader": "^6.2.0", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "sharp": "^0.32.3", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/lqip-loader/node_modules/sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "node_modules/@docusaurus/core/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", + "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/lqip-loader": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.9.2.tgz", + "integrity": "sha512-Q9QO0E+HLKhcpKVOIXRVBdJ1bbxxpfSwBll5NsmGxcx1fArH0fFi68cpEztqBg7WwbFRb976MTlqlBuGrMLpuw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.9.2", + "file-loader": "^6.2.0", + "lodash": "^4.17.21", + "sharp": "^0.32.3", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/lqip-loader/node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -3677,14 +3853,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", - "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -3715,6 +3891,83 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, "node_modules/@docusaurus/module-type-aliases": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.1.tgz", @@ -3758,45 +4011,10 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", - "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "cheerio": "1.0.0-rc.12", - "combine-promises": "^1.1.0", - "feed": "^4.2.2", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "schema-dts": "^1.1.2", - "srcset": "^4.0.0", - "tslib": "^2.6.0", - "unist-util-visit": "^5.0.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/babel": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", + "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3807,9 +4025,10 @@ "@babel/preset-react": "^7.25.9", "@babel/preset-typescript": "^7.25.9", "@babel/runtime": "^7.25.9", + "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3818,18 +4037,18 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/bundler": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", + "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", + "@docusaurus/babel": "3.9.2", + "@docusaurus/cssnano-preset": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", @@ -3847,7 +4066,7 @@ "tslib": "^2.6.0", "url-loader": "^4.1.1", "webpack": "^5.95.0", - "webpackbar": "^7.0.0" + "webpackbar": "^6.0.1" }, "engines": { "node": ">=20.0" @@ -3861,19 +4080,19 @@ } } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/core": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", + "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", + "@docusaurus/babel": "3.9.2", + "@docusaurus/bundler": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3885,7 +4104,7 @@ "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", - "execa": "^5.1.1", + "execa": "5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", @@ -3896,12 +4115,12 @@ "prompts": "^2.4.2", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", "react-router": "^5.3.4", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.4", "semver": "^7.5.4", - "serve-handler": "^6.1.7", + "serve-handler": "^6.1.6", "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", @@ -3917,68 +4136,35 @@ "node": ">=20.0" }, "peerDependencies": { - "@docusaurus/faster": "*", "@mdx-js/react": "^3.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/cssnano-preset": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", + "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/mdx-loader": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", + "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -4009,71 +4195,43 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/types": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=20.0" + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/types/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" }, "engines": { - "node": ">=20.0" + "node": ">=10.0.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/css-loader": { + "node_modules/@docusaurus/plugin-client-redirects/node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", @@ -4108,55 +4266,115 @@ } } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "node_modules/@docusaurus/plugin-client-redirects/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/@docusaurus/plugin-client-redirects/node_modules/markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", "license": "MIT", "dependencies": { - "ansis": "^3.2.0", + "repeat-string": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@docusaurus/plugin-client-redirects/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@docusaurus/plugin-client-redirects/node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@docusaurus/plugin-client-redirects/node_modules/webpackbar": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", + "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", "consola": "^3.2.3", + "figures": "^3.2.0", + "markdown-table": "^2.0.0", "pretty-time": "^1.1.0", - "std-env": "^3.7.0" + "std-env": "^3.7.0", + "wrap-ansi": "^7.0.0" }, "engines": { "node": ">=14.21.3" }, "peerDependencies": { - "@rspack/core": "*", "webpack": "3 || 4 || 5" + } + }, + "node_modules/@docusaurus/plugin-client-redirects/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@docusaurus/plugin-content-docs": { + "node_modules/@docusaurus/plugin-content-blog": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", - "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", + "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", "license": "MIT", "dependencies": { "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/module-type-aliases": "3.10.1", "@docusaurus/theme-common": "3.10.1", "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@types/react-router-config": "^5.0.7", + "cheerio": "1.0.0-rc.12", "combine-promises": "^1.1.0", + "feed": "^4.2.2", "fs-extra": "^11.1.1", - "js-yaml": "^4.1.0", "lodash": "^4.17.21", "schema-dts": "^1.1.2", + "srcset": "^4.0.0", "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", "utility-types": "^3.10.0", "webpack": "^5.88.1" }, @@ -4164,216 +4382,111 @@ "node": ">=20.0" }, "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/babel": { + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/bundler": { + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", "@docusaurus/logger": "3.10.1", "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", + "resolve-pathname": "^3.0.0", "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/cssnano-preset": { + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-common": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/mdx-loader": { + "node_modules/@docusaurus/plugin-content-docs": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", + "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "schema-dts": "^1.1.2", "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", + "utility-types": "^3.10.0", "webpack": "^5.88.1" }, "engines": { @@ -4384,6 +4497,19 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -4448,68 +4574,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, "node_modules/@docusaurus/plugin-content-pages": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.1.tgz", @@ -4533,223 +4597,113 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/babel": { + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/bundler": { + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", "@docusaurus/logger": "3.10.1", "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", + "escape-string-regexp": "^4.0.0", "execa": "^5.1.1", + "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", + "resolve-pathname": "^3.0.0", "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/cssnano-preset": { + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/plugin-css-cascade-layers": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", + "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/mdx-loader": { + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" + "chalk": "^4.1.2", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", @@ -4781,7 +4735,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-common": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", @@ -4794,7 +4748,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", @@ -4813,249 +4767,105 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "node_modules/@docusaurus/plugin-debug": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", + "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", "license": "MIT", "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^2.3.0", + "tslib": "^2.6.0" }, "engines": { - "node": ">=14.21.3" + "node": ">=20.0" }, "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers": { + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", - "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/babel": { + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", "@docusaurus/logger": "3.10.1", "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", + "escape-string-regexp": "^4.0.0", "execa": "^5.1.1", + "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", + "resolve-pathname": "^3.0.0", "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/cssnano-preset": { + "node_modules/@docusaurus/plugin-google-analytics": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", + "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/logger": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", @@ -5068,46 +4878,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", @@ -5139,7 +4910,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-common": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", @@ -5152,7 +4923,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", @@ -5171,2185 +4942,113 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", + "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", "license": "MIT", "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@types/gtag.js": "^0.0.20", + "tslib": "^2.6.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=20.0" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-debug": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", - "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "fs-extra": "^11.1.1", - "react-json-view-lite": "^2.3.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", - "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", - "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@types/gtag.js": "^0.0.20", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", - "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.2.tgz", - "integrity": "sha512-YYYbmC2wSYFd7o4//5rPXt9+DkZwfwjCUmyGi5OIVqEbwELK80o3COXs2Xd0BtVIpuRvG7pKCYrMQwVo32Y9qw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/lqip-loader": "3.9.2", - "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "sharp": "^0.32.3", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "jimp": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "jimp": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", - "hasInstallScript": true, - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", - "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "fs-extra": "^11.1.1", - "sitemap": "^7.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-svgr": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", - "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@svgr/core": "8.1.0", - "@svgr/webpack": "^8.1.0", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/cssnano-preset": { + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-common": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/mdx-loader": { + "node_modules/@docusaurus/plugin-google-tag-manager": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", + "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" @@ -7359,7 +5058,20 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", @@ -7391,7 +5103,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-common": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", @@ -7404,7 +5116,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", @@ -7423,102 +5135,40 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-svgr/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "node_modules/@docusaurus/plugin-ideal-image": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.2.tgz", + "integrity": "sha512-YYYbmC2wSYFd7o4//5rPXt9+DkZwfwjCUmyGi5OIVqEbwELK80o3COXs2Xd0BtVIpuRvG7pKCYrMQwVo32Y9qw==", "license": "MIT", "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" + "@docusaurus/core": "3.9.2", + "@docusaurus/lqip-loader": "3.9.2", + "@docusaurus/responsive-loader": "^1.7.0", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", + "sharp": "^0.32.3", + "tslib": "^2.6.0", + "webpack": "^5.88.1" }, "engines": { - "node": ">=14.21.3" + "node": ">=20.0" }, "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" + "jimp": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { + "jimp": { "optional": true } } }, - "node_modules/@docusaurus/preset-classic": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.10.1.tgz", - "integrity": "sha512-YO/FL8v1zmbxoTso6mjMz/RDjhaTJxb1UpFFTDdY5847LLDCeyYiYlrhyTbgN1RIN3xnkLKZ9Lj1x8hUzI4JOg==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/plugin-content-blog": "3.10.1", - "@docusaurus/plugin-content-docs": "3.10.1", - "@docusaurus/plugin-content-pages": "3.10.1", - "@docusaurus/plugin-css-cascade-layers": "3.10.1", - "@docusaurus/plugin-debug": "3.10.1", - "@docusaurus/plugin-google-analytics": "3.10.1", - "@docusaurus/plugin-google-gtag": "3.10.1", - "@docusaurus/plugin-google-tag-manager": "3.10.1", - "@docusaurus/plugin-sitemap": "3.10.1", - "@docusaurus/plugin-svgr": "3.10.1", - "@docusaurus/theme-classic": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/theme-search-algolia": "3.10.1", - "@docusaurus/types": "3.10.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/babel": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", + "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -7529,9 +5179,10 @@ "@babel/preset-react": "^7.25.9", "@babel/preset-typescript": "^7.25.9", "@babel/runtime": "^7.25.9", + "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -7540,18 +5191,18 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/bundler": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", + "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", + "@docusaurus/babel": "3.9.2", + "@docusaurus/cssnano-preset": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", @@ -7569,7 +5220,7 @@ "tslib": "^2.6.0", "url-loader": "^4.1.1", "webpack": "^5.95.0", - "webpackbar": "^7.0.0" + "webpackbar": "^6.0.1" }, "engines": { "node": ">=20.0" @@ -7583,19 +5234,19 @@ } } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/core": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", + "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", + "@docusaurus/babel": "3.9.2", + "@docusaurus/bundler": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -7607,7 +5258,7 @@ "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", - "execa": "^5.1.1", + "execa": "5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", @@ -7618,12 +5269,12 @@ "prompts": "^2.4.2", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", "react-router": "^5.3.4", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.4", "semver": "^7.5.4", - "serve-handler": "^6.1.7", + "serve-handler": "^6.1.6", "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", @@ -7639,18 +5290,12 @@ "node": ">=20.0" }, "peerDependencies": { - "@docusaurus/faster": "*", "@mdx-js/react": "^3.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/core/node_modules/webpack-merge": { + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/core/node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", @@ -7664,10 +5309,10 @@ "node": ">=18.0.0" } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/cssnano-preset": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/cssnano-preset": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", + "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", @@ -7679,28 +5324,15 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/mdx-loader": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/mdx-loader": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", + "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -7731,71 +5363,29 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/types": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=20.0" + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/preset-classic/node_modules/css-loader": { + "node_modules/@docusaurus/plugin-ideal-image/node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", @@ -7830,303 +5420,214 @@ } } }, - "node_modules/@docusaurus/preset-classic/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/@docusaurus/plugin-ideal-image/node_modules/markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", "license": "MIT", "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" + "repeat-string": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" }, "engines": { - "node": ">=14.21.3" + "node": ">=14.15.0" }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@docusaurus/plugin-ideal-image/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/@docusaurus/responsive-loader": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz", - "integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/webpackbar": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", + "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", + "license": "MIT", "dependencies": { - "loader-utils": "^2.0.0" + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "consola": "^3.2.3", + "figures": "^3.2.0", + "markdown-table": "^2.0.0", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.21.3" }, "peerDependencies": { - "jimp": "*", - "sharp": "*" - }, - "peerDependenciesMeta": { - "jimp": { - "optional": true - }, - "sharp": { - "optional": true - } + "webpack": "3 || 4 || 5" } }, - "node_modules/@docusaurus/theme-classic": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", - "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/module-type-aliases": "3.10.1", - "@docusaurus/plugin-content-blog": "3.10.1", - "@docusaurus/plugin-content-docs": "3.10.1", - "@docusaurus/plugin-content-pages": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/theme-translations": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", - "infima": "0.2.0-alpha.45", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.5.4", - "prism-react-renderer": "^2.3.0", - "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", - "rtlcss": "^4.1.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=20.0" + "node": ">=10" }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/babel": { + "node_modules/@docusaurus/plugin-sitemap": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", + "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", + "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/bundler": { + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" + "chalk": "^4.1.2", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/core": { + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/utils": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", + "escape-string-regexp": "^4.0.0", "execa": "^5.1.1", + "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", + "resolve-pathname": "^3.0.0", "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/cssnano-preset": { + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-common": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/mdx-loader": { + "node_modules/@docusaurus/plugin-svgr": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", + "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", "webpack": "^5.88.1" }, "engines": { @@ -8137,20 +5638,20 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/theme-translations": { + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", - "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "fs-extra": "^11.1.1", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", @@ -8182,7 +5683,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-common": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", @@ -8195,7 +5696,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", @@ -8214,84 +5715,89 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "node_modules/@docusaurus/preset-classic": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.10.1.tgz", + "integrity": "sha512-YO/FL8v1zmbxoTso6mjMz/RDjhaTJxb1UpFFTDdY5847LLDCeyYiYlrhyTbgN1RIN3xnkLKZ9Lj1x8hUzI4JOg==", "license": "MIT", "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "@docusaurus/core": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/plugin-css-cascade-layers": "3.10.1", + "@docusaurus/plugin-debug": "3.10.1", + "@docusaurus/plugin-google-analytics": "3.10.1", + "@docusaurus/plugin-google-gtag": "3.10.1", + "@docusaurus/plugin-google-tag-manager": "3.10.1", + "@docusaurus/plugin-sitemap": "3.10.1", + "@docusaurus/plugin-svgr": "3.10.1", + "@docusaurus/theme-classic": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-search-algolia": "3.10.1", + "@docusaurus/types": "3.10.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", + "node_modules/@docusaurus/responsive-loader": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz", + "integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==", "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" + "loader-utils": "^2.0.0" }, "engines": { - "node": ">=14.21.3" + "node": ">=12" }, "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" + "jimp": "*", + "sharp": "*" }, "peerDependenciesMeta": { - "@rspack/core": { + "jimp": { "optional": true }, - "webpack": { + "sharp": { "optional": true } } }, - "node_modules/@docusaurus/theme-common": { + "node_modules/@docusaurus/theme-classic": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.1.tgz", - "integrity": "sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", + "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", "@docusaurus/mdx-loader": "3.10.1", "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", - "parse-numeric-range": "^1.3.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.45", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.5.4", "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", "tslib": "^2.6.0", "utility-types": "^3.10.0" }, @@ -8299,12 +5805,11 @@ "node": ">=20.0" }, "peerDependencies": { - "@docusaurus/plugin-content-docs": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/logger": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", @@ -8317,46 +5822,20 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/mdx-loader": { + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/theme-translations": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", + "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", @@ -8388,7 +5867,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-common": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", @@ -8401,7 +5880,7 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-validation": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", @@ -8420,231 +5899,115 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.1.tgz", - "integrity": "sha512-OTaARARVZj2GvkJQjB+1jOIxntRaXea+G+fMsNqrZBAU1O1vJKDW22R7kECOHW27oJCLFN9HKaZeRrfAUyviug==", - "license": "MIT", - "dependencies": { - "@algolia/autocomplete-core": "^1.19.2", - "@docsearch/react": "^3.9.0 || ^4.3.2", - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/plugin-content-docs": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/theme-translations": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "algoliasearch": "^5.37.0", - "algoliasearch-helper": "^3.26.0", - "clsx": "^2.0.0", - "eta": "^2.2.0", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/babel": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", - "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/bundler": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", - "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.10.1", - "@docusaurus/cssnano-preset": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^7.0.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/core": { + "node_modules/@docusaurus/theme-common": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", - "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.1.tgz", + "integrity": "sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.10.1", - "@docusaurus/bundler": "3.10.1", - "@docusaurus/logger": "3.10.1", "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "^5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.7", - "tinypool": "^1.0.2", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "utility-types": "^3.10.0" }, "engines": { "node": ">=20.0" }, "peerDependencies": { - "@docusaurus/faster": "*", - "@mdx-js/react": "^3.0.0", + "@docusaurus/plugin-content-docs": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/cssnano-preset": { + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/logger": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", - "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/mdx-loader": { + "node_modules/@docusaurus/theme-search-algolia": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", - "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.1.tgz", + "integrity": "sha512-OTaARARVZj2GvkJQjB+1jOIxntRaXea+G+fMsNqrZBAU1O1vJKDW22R7kECOHW27oJCLFN9HKaZeRrfAUyviug==", "license": "MIT", "dependencies": { + "@algolia/autocomplete-core": "^1.19.2", + "@docsearch/react": "^3.9.0 || ^4.3.2", + "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", + "algoliasearch": "^5.37.0", + "algoliasearch-helper": "^3.26.0", + "clsx": "^2.0.0", + "eta": "^2.2.0", "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", + "lodash": "^4.17.21", "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" + "utility-types": "^3.10.0" }, "engines": { "node": ">=20.0" @@ -8654,6 +6017,19 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/theme-translations": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", @@ -8731,82 +6107,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/webpackbar": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", - "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", - "license": "MIT", - "dependencies": { - "ansis": "^3.2.0", - "consola": "^3.2.3", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@rspack/core": "*", - "webpack": "3 || 4 || 5" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, "node_modules/@docusaurus/theme-translations": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz", @@ -10876,9 +8176,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.24", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz", - "integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", "funding": [ { "type": "opencollective", @@ -10895,8 +8195,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.1", - "caniuse-lite": "^1.0.30001766", + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -11097,12 +8397,15 @@ ] }, "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "version": "2.10.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", + "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/batch": { @@ -11285,9 +8588,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "funding": [ { "type": "opencollective", @@ -11304,11 +8607,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -11417,14 +8720,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" }, "engines": { @@ -11505,9 +8808,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001768", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001768.tgz", - "integrity": "sha512-qY3aDRZC5nWPgHUgIB84WL+nySuo19wk0VJpp/XI9T34lrvkyhRvNVOFJOp2kxClQhiFBu+TaUSudf6oa3vkSA==", + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", "funding": [ { "type": "opencollective", @@ -12150,9 +9453,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.48.0.tgz", - "integrity": "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.49.0.tgz", + "integrity": "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -12269,9 +9572,9 @@ } }, "node_modules/css-declaration-sorter": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.3.1.tgz", - "integrity": "sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz", + "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==", "license": "ISC", "engines": { "node": "^14 || ^16 || >=18" @@ -12489,9 +9792,9 @@ } }, "node_modules/cssdb": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.7.1.tgz", - "integrity": "sha512-+F6LKx48RrdGOtE4DT5jz7Uo+VeyKXpK797FAevIkzjV8bMHz6xTO5F7gNDcRCHmPgD5jj2g6QCsY9zmVrh38A==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.9.0.tgz", + "integrity": "sha512-J8jOU/hLjaXcO1LldOLraJSQpfLXRKof0I7mtbRyOy2AAXgqst0x9rlgi2qXeD6d0ou3ZLqcPAMqYVbpCbrxEw==", "funding": [ { "type": "opencollective", @@ -13163,9 +10466,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "version": "1.5.354", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.354.tgz", + "integrity": "sha512-JaBHwWcfIdmSAfWM5l3uwjGd431j8YEMikZ+K/2nXVuBqJKyZ0f+2h4n4JY5AyNiZmnY9qQr2RU3v9DxDmHMNg==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -18222,9 +15525,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz", - "integrity": "sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", @@ -18396,9 +15699,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.44", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", + "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", "license": "MIT" }, "node_modules/nopt": { @@ -18479,9 +15782,9 @@ } }, "node_modules/null-loader/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -23887,75 +21190,30 @@ } }, "node_modules/webpackbar": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", - "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", "license": "MIT", "dependencies": { - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", + "ansis": "^3.2.0", "consola": "^3.2.3", - "figures": "^3.2.0", - "markdown-table": "^2.0.0", "pretty-time": "^1.1.0", - "std-env": "^3.7.0", - "wrap-ansi": "^7.0.0" + "std-env": "^3.7.0" }, "engines": { "node": ">=14.21.3" }, "peerDependencies": { + "@rspack/core": "*", "webpack": "3 || 4 || 5" - } - }, - "node_modules/webpackbar/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/webpackbar/node_modules/markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "license": "MIT", - "dependencies": { - "repeat-string": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/webpackbar/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpackbar/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/websocket-driver": { diff --git a/site/package.json b/site/package.json index 62b40c9da7..73ba5d2512 100644 --- a/site/package.json +++ b/site/package.json @@ -14,7 +14,7 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.9.2", + "@docusaurus/core": "^3.10.1", "@docusaurus/plugin-client-redirects": "^3.9.2", "@docusaurus/plugin-ideal-image": "^3.9.2", "@docusaurus/preset-classic": "^3.10.1", From 8f69a1767704d500b01b81b12602c816c99ab8e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 01:41:26 +0000 Subject: [PATCH 407/448] deps: bump @docusaurus/plugin-ideal-image from 3.9.2 to 3.10.1 in /site (#2347) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@docusaurus/plugin-ideal-image](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-ideal-image) from 3.9.2 to 3.10.1.
Release notes

Sourced from @​docusaurus/plugin-ideal-image's releases.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Changelog

Sourced from @​docusaurus/plugin-ideal-image's changelog.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Commits
  • 41c1a45 v3.10.1
  • 1451780 chore(ci): fixes for the npm trusted publishing workflow (#11823)
  • 5dff744 chore(ci): add Trusted Publishing release workflow through dispatch action (#...
  • bbc7269 chore(monorepo): upgrade React packages to v19 (#11698)
  • 81248ee chore(monorepo): upgrade to Jest 30 (#11702)
  • 50e8f95 fix(ideal-image): \<IdealImage> should forward remaining props to the underl...
  • bca9ce7 chore: release v3.9.2 (#11491)
  • See full diff in compare view
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​docusaurus/plugin-ideal-image since your current version.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 405 ++++++++--------------------------------- site/package.json | 2 +- 2 files changed, 72 insertions(+), 335 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 698538e817..b0505d92e0 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@docusaurus/core": "^3.10.1", "@docusaurus/plugin-client-redirects": "^3.9.2", - "@docusaurus/plugin-ideal-image": "^3.9.2", + "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", "@types/react": "^18.3.28", @@ -3814,12 +3814,12 @@ } }, "node_modules/@docusaurus/lqip-loader": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.9.2.tgz", - "integrity": "sha512-Q9QO0E+HLKhcpKVOIXRVBdJ1bbxxpfSwBll5NsmGxcx1fArH0fFi68cpEztqBg7WwbFRb976MTlqlBuGrMLpuw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.10.1.tgz", + "integrity": "sha512-ushByv88FWxsh3BS9QccWcEbKsW0QnNvWnl0+NCLe7weL5AkHS4HnSDszGMSzn2v5jidT4QjOVHacNVsU5I9Lw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", + "@docusaurus/logger": "3.10.1", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", @@ -3829,6 +3829,19 @@ "node": ">=20.0" } }, + "node_modules/@docusaurus/lqip-loader/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, "node_modules/@docusaurus/lqip-loader/node_modules/sharp": { "version": "0.32.6", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", @@ -5136,17 +5149,17 @@ } }, "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.9.2.tgz", - "integrity": "sha512-YYYbmC2wSYFd7o4//5rPXt9+DkZwfwjCUmyGi5OIVqEbwELK80o3COXs2Xd0BtVIpuRvG7pKCYrMQwVo32Y9qw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.10.1.tgz", + "integrity": "sha512-zIjQ/BtFS6YwEgnk9ypZxuSnA/Z011Z9cuaawKVfgyT7T+vuGx6T6ZgKur0IFnOkpI7EfI1DhbfdABCtfEzWFA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/lqip-loader": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/lqip-loader": "3.10.1", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "sharp": "^0.32.3", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -5165,278 +5178,81 @@ } } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/babel": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", - "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/runtime-corejs3": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", + "chalk": "^4.1.2", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/bundler": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", - "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.9.2", - "@docusaurus/cssnano-preset": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^6.0.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/core": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", - "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.9.2", - "@docusaurus/bundler": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "5.1.1", "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.6", - "tinypool": "^1.0.2", + "resolve-pathname": "^3.0.0", "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - }, - "peerDependencies": { - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/cssnano-preset": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", - "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/mdx-loader": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", - "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "license": "MIT", - "dependencies": { - "repeat-string": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node": ">=20.0" } }, "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { @@ -5461,59 +5277,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/webpackbar": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", - "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "consola": "^3.2.3", - "figures": "^3.2.0", - "markdown-table": "^2.0.0", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "webpack": "3 || 4 || 5" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@docusaurus/plugin-sitemap": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", @@ -5822,19 +5585,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/theme-translations": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", - "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", - "license": "MIT", - "dependencies": { - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -6030,19 +5780,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/theme-translations": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", - "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", - "license": "MIT", - "dependencies": { - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -6108,9 +5845,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz", - "integrity": "sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", + "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", diff --git a/site/package.json b/site/package.json index 73ba5d2512..f7acb8ba2b 100644 --- a/site/package.json +++ b/site/package.json @@ -16,7 +16,7 @@ "dependencies": { "@docusaurus/core": "^3.10.1", "@docusaurus/plugin-client-redirects": "^3.9.2", - "@docusaurus/plugin-ideal-image": "^3.9.2", + "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", "@types/react": "^18.3.28", From 5b72798e38a84aec9febc454f5486d28e1d5090b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 02:45:57 +0000 Subject: [PATCH 408/448] deps: bump @docusaurus/plugin-client-redirects from 3.9.2 to 3.10.1 in /site (#2351) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) from 3.9.2 to 3.10.1.
Release notes

Sourced from @​docusaurus/plugin-client-redirects's releases.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Changelog

Sourced from @​docusaurus/plugin-client-redirects's changelog.

3.10.1 (2026-04-30)

:bug: Bug Fix

  • docusaurus-bundler
    • #11981 fix(bundler): fix v3 webpackbar bug due to webpack breaking change (@​slorber)

:wrench: Maintenance

  • docusaurus

Committers: 1

3.10.0 (2026-04-07)

:rocket: New Feature

  • docusaurus-types, docusaurus
    • #11896 feat(core): add future.v4.mdx1CompatDisabledByDefault flag (@​slorber)
    • #11797 feat(core): promote siteConfig.storage to stable + add future.v4.siteStorageNamespacing flag [Claude] (@​slorber)
    • #11571 feat(core): support custom html elements in head tags (@​lebalz)
  • create-docusaurus
    • #11897 feat(create-docusaurus): update init template to .mdx extension and strict MDX syntax (@​slorber)
    • #11696 feat(create-docusaurus): Newly initialized TS sites should use "strict: true" (@​slorber)
    • #11611 feat(create-docusaurus): enable creation in current directory (@​Mcheung7272)
  • Other
    • #11874 feat(ci): improve npm supply chain security - improve Dependabot config (@​slorber)
    • #11712 feat(publish): Use trusted publishing (OIDC) for canary releases (@​slorber)
  • create-docusaurus, docusaurus-bundler, docusaurus-plugin-content-blog, docusaurus-plugin-content-docs, docusaurus-plugin-content-pages, docusaurus-plugin-pwa, docusaurus-types, docusaurus
    • #11802 feat(core): Docusaurus Faster is stable + v4 future flag turns it on by default (@​slorber)
  • docusaurus-mdx-loader, docusaurus-utils, docusaurus
    • #11777 feat(cli): write-heading-ids CLI now supports the --syntax and --migrate options (@​slorber)
  • docusaurus-mdx-loader
    • #11755 feat(mdx-loader): add support for explicit headingId based on MD/MDX comments (@​slorber)
  • docusaurus-theme-live-codeblock, docusaurus-theme-translations
  • docusaurus-theme-classic, docusaurus-theme-common
    • #11734 feat(theme): Split <DocCard>, improve extensibility, better handling of emoji icons, stable classNames (@​slorber)
    • #11733 feat(theme): Use React context for <Tabs>, allow custom <TabItem> components (@​slorber)
  • docusaurus-faster, docusaurus
    • #11715 feat(bundler): upgrade to Rspack 1.7, remove useless experimental feature flags (@​slorber)
  • docusaurus-plugin-content-pages
  • docusaurus-mdx-loader, docusaurus-theme-classic
    • #11642 feat(mdx-loader): add admonitions directive support for class/id shortcuts (@​lebalz)
  • docusaurus-theme-classic

... (truncated)

Commits
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​docusaurus/plugin-client-redirects since your current version.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 2224 ++++------------------------------------ site/package.json | 2 +- 2 files changed, 222 insertions(+), 2004 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index b0505d92e0..1552ab67f3 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "dependencies": { "@docusaurus/core": "^3.10.1", - "@docusaurus/plugin-client-redirects": "^3.9.2", + "@docusaurus/plugin-client-redirects": "^3.10.1", "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", @@ -1926,18 +1926,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.2.tgz", - "integrity": "sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw==", - "license": "MIT", - "dependencies": { - "core-js-pure": "^3.48.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", @@ -3433,64 +3421,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/babel/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/babel/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/babel/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/bundler": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", @@ -3534,64 +3464,6 @@ } } }, - "node_modules/@docusaurus/bundler/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/bundler/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/bundler/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/bundler/node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -3694,83 +3566,6 @@ } } }, - "node_modules/@docusaurus/core/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/core/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/core/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/core/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/core/node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", @@ -3801,9 +3596,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", - "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -3829,19 +3624,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/lqip-loader/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/lqip-loader/node_modules/sharp": { "version": "0.32.6", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", @@ -3904,1394 +3686,131 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/module-type-aliases": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.1.tgz", + "integrity": "sha512-YoOZKUdGlp8xSYhuAkGdSo5Ydkbq4V4eK3sD8v0a2hloxCWdQbNBhkc+Ko9QyjpESc0BYcIGM5iHVAy5hdFV6w==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" + "@docusaurus/types": "3.10.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, - "engines": { - "node": ">=20.0" + "peerDependencies": { + "react": "*", + "react-dom": "*" } }, - "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-client-redirects": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.10.1.tgz", + "integrity": "sha512-LHgd+YDvkhfOHMAE6XtUng3DQNzVM765RqVRrMJgHtzAvfopQhY6ieprqjxDVBdv21cLma6I0jHr+YCZH8fL9A==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", + "@docusaurus/utils-validation": "3.10.1", + "eta": "^2.2.0", "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-content-blog": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/mdx-loader/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/module-type-aliases": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.1.tgz", - "integrity": "sha512-YoOZKUdGlp8xSYhuAkGdSo5Ydkbq4V4eK3sD8v0a2hloxCWdQbNBhkc+Ko9QyjpESc0BYcIGM5iHVAy5hdFV6w==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@docusaurus/plugin-client-redirects": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.9.2.tgz", - "integrity": "sha512-lUgMArI9vyOYMzLRBUILcg9vcPTCyyI2aiuXq/4npcMVqOr6GfmwtmBYWSbNMlIUM0147smm4WhpXD0KFboffw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "eta": "^2.2.0", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/babel": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", - "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.25.9", - "@babel/preset-env": "^7.25.9", - "@babel/preset-react": "^7.25.9", - "@babel/preset-typescript": "^7.25.9", - "@babel/runtime": "^7.25.9", - "@babel/runtime-corejs3": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "babel-plugin-dynamic-import-node": "^2.3.3", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/bundler": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", - "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.9.2", - "@docusaurus/cssnano-preset": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "babel-loader": "^9.2.1", - "clean-css": "^5.3.3", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.11.0", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "file-loader": "^6.2.0", - "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.2", - "null-loader": "^4.0.1", - "postcss": "^8.5.4", - "postcss-loader": "^7.3.4", - "postcss-preset-env": "^10.2.1", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "webpack": "^5.95.0", - "webpackbar": "^6.0.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/faster": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/faster": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/core": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", - "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.9.2", - "@docusaurus/bundler": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "core-js": "^3.31.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "execa": "5.1.1", - "fs-extra": "^11.1.1", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.6.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "p-map": "^4.0.0", - "prompts": "^2.4.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.6", - "tinypool": "^1.0.2", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "webpack": "^5.95.0", - "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^5.2.2", - "webpack-merge": "^6.0.1" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/cssnano-preset": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", - "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", - "license": "MIT", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.5.4", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/mdx-loader": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", - "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^2.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/@docusaurus/types/node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "license": "MIT", - "dependencies": { - "repeat-string": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/webpackbar": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", - "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "consola": "^3.2.3", - "figures": "^3.2.0", - "markdown-table": "^2.0.0", - "pretty-time": "^1.1.0", - "std-env": "^3.7.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "webpack": "3 || 4 || 5" - } - }, - "node_modules/@docusaurus/plugin-client-redirects/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", - "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "cheerio": "1.0.0-rc.12", - "combine-promises": "^1.1.0", - "feed": "^4.2.2", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "schema-dts": "^1.1.2", - "srcset": "^4.0.0", - "tslib": "^2.6.0", - "unist-util-visit": "^5.0.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", - "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/module-type-aliases": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@types/react-router-config": "^5.0.7", - "combine-promises": "^1.1.0", - "fs-extra": "^11.1.1", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "schema-dts": "^1.1.2", - "tslib": "^2.6.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.1.tgz", - "integrity": "sha512-huJpaRPMl42nsFwuCXvV8bVDj2MazuwRJIUylI/RSlmZeJssVoZXeCjVf1y+1Drtpa9SKcdGn8yoJ76IRJijtw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", - "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-css-cascade-layers/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", - "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "fs-extra": "^11.1.1", - "react-json-view-lite": "^2.3.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", - "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", - "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@types/gtag.js": "^0.0.20", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", - "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", + "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", "license": "MIT", "dependencies": { "@docusaurus/core": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/theme-common": "3.10.1", "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", + "@docusaurus/utils-validation": "3.10.1", + "cheerio": "1.0.0-rc.12", + "combine-promises": "^1.1.0", + "feed": "^4.2.2", "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", + "schema-dts": "^1.1.2", + "srcset": "^4.0.0", "tslib": "^2.6.0", - "url-loader": "^4.1.1", + "unist-util-visit": "^5.0.0", "utility-types": "^3.10.0", "webpack": "^5.88.1" }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.10.1.tgz", - "integrity": "sha512-zIjQ/BtFS6YwEgnk9ypZxuSnA/Z011Z9cuaawKVfgyT7T+vuGx6T6ZgKur0IFnOkpI7EfI1DhbfdABCtfEzWFA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/lqip-loader": "3.10.1", - "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "sharp": "^0.32.3", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, "engines": { "node": ">=20.0" }, "peerDependencies": { - "jimp": "*", + "@docusaurus/plugin-content-docs": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "jimp": { - "optional": true - } - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-content-docs": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", + "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/theme-common": "3.10.1", "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", + "@docusaurus/utils-validation": "3.10.1", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", + "schema-dts": "^1.1.2", "tslib": "^2.6.0", - "url-loader": "^4.1.1", "utility-types": "^3.10.0", "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", - "hasInstallScript": true, - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" - }, - "engines": { - "node": ">=14.15.0" }, - "funding": { - "url": "https://opencollective.com/libvips" + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-sitemap": { + "node_modules/@docusaurus/plugin-content-pages": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", - "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.1.tgz", + "integrity": "sha512-huJpaRPMl42nsFwuCXvV8bVDj2MazuwRJIUylI/RSlmZeJssVoZXeCjVf1y+1Drtpa9SKcdGn8yoJ76IRJijtw==", "license": "MIT", "dependencies": { "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", "@docusaurus/utils-validation": "3.10.1", "fs-extra": "^11.1.1", - "sitemap": "^7.1.1", - "tslib": "^2.6.0" + "tslib": "^2.6.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" @@ -5301,97 +3820,73 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-css-cascade-layers": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", + "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", + "@docusaurus/core": "3.10.1", "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-debug": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", + "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/plugin-google-analytics": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", + "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr": { + "node_modules/@docusaurus/plugin-google-gtag": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", - "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", + "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", "license": "MIT", "dependencies": { "@docusaurus/core": "3.10.1", "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@svgr/core": "8.1.0", - "@svgr/webpack": "^8.1.0", - "tslib": "^2.6.0", - "webpack": "^5.88.1" + "@types/gtag.js": "^0.0.20", + "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" @@ -5401,81 +3896,122 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/logger": { + "node_modules/@docusaurus/plugin-google-tag-manager": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", + "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils": { + "node_modules/@docusaurus/plugin-ideal-image": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.10.1.tgz", + "integrity": "sha512-zIjQ/BtFS6YwEgnk9ypZxuSnA/Z011Z9cuaawKVfgyT7T+vuGx6T6ZgKur0IFnOkpI7EfI1DhbfdABCtfEzWFA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", + "@docusaurus/core": "3.10.1", + "@docusaurus/lqip-loader": "3.10.1", + "@docusaurus/responsive-loader": "^1.7.0", + "@docusaurus/theme-translations": "3.10.1", "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", + "@docusaurus/utils-validation": "3.10.1", + "sharp": "^0.32.3", "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "jimp": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "jimp": { + "optional": true + } + } + }, + "node_modules/@docusaurus/plugin-ideal-image/node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-common": { + "node_modules/@docusaurus/plugin-sitemap": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", + "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-svgr/node_modules/@docusaurus/utils-validation": { + "node_modules/@docusaurus/plugin-svgr": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", + "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.10.1", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" + "@docusaurus/utils-validation": "3.10.1", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", + "tslib": "^2.6.0", + "webpack": "^5.88.1" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/preset-classic": { @@ -5533,120 +4069,43 @@ }, "node_modules/@docusaurus/theme-classic": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", - "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.10.1", - "@docusaurus/logger": "3.10.1", - "@docusaurus/mdx-loader": "3.10.1", - "@docusaurus/module-type-aliases": "3.10.1", - "@docusaurus/plugin-content-blog": "3.10.1", - "@docusaurus/plugin-content-docs": "3.10.1", - "@docusaurus/plugin-content-pages": "3.10.1", - "@docusaurus/theme-common": "3.10.1", - "@docusaurus/theme-translations": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "@docusaurus/utils-validation": "3.10.1", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", - "infima": "0.2.0-alpha.45", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.5.4", - "prism-react-renderer": "^2.3.0", - "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", - "rtlcss": "^4.1.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=20.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", + "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", "license": "MIT", "dependencies": { + "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/types": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.45", "lodash": "^4.17.21", - "tslib": "^2.6.0" + "nprogress": "^0.2.0", + "postcss": "^8.5.4", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" }, "engines": { "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, "node_modules/@docusaurus/theme-common": { @@ -5677,64 +4136,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/theme-search-algolia": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.1.tgz", @@ -5767,83 +4168,6 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/logger": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", - "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/types": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "escape-string-regexp": "^4.0.0", - "execa": "^5.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "p-queue": "^6.6.2", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils-common": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", - "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", - "license": "MIT", - "dependencies": { - "@docusaurus/types": "3.10.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia/node_modules/@docusaurus/utils-validation": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", - "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", - "license": "MIT", - "dependencies": { - "@docusaurus/logger": "3.10.1", - "@docusaurus/utils": "3.10.1", - "@docusaurus/utils-common": "3.10.1", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=20.0" - } - }, "node_modules/@docusaurus/theme-translations": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", @@ -5887,16 +4211,16 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.2.tgz", - "integrity": "sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-common": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", "escape-string-regexp": "^4.0.0", - "execa": "5.1.1", + "execa": "^5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "github-slugger": "^1.5.0", @@ -5919,49 +4243,27 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.2.tgz", - "integrity": "sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.2", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { "node": ">=20.0" } }, - "node_modules/@docusaurus/utils-common/node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@docusaurus/utils-validation": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz", - "integrity": "sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -5972,28 +4274,6 @@ "node": ">=20.0" } }, - "node_modules/@docusaurus/utils/node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/mdast": "^4.0.2", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.95.0", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@emnapi/runtime": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", @@ -7780,33 +6060,6 @@ "node": ">=8" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -9189,17 +7442,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/core-js-pure": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.49.0.tgz", - "integrity": "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -10845,30 +9087,6 @@ "node": ">=0.4.0" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/file-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", diff --git a/site/package.json b/site/package.json index f7acb8ba2b..8f359d4348 100644 --- a/site/package.json +++ b/site/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@docusaurus/core": "^3.10.1", - "@docusaurus/plugin-client-redirects": "^3.9.2", + "@docusaurus/plugin-client-redirects": "^3.10.1", "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", From 8f4f29df780f4fdbeffc588c771beaefd08a7c5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 04:47:33 +0000 Subject: [PATCH 409/448] deps: bump react-dom from 19.2.5 to 19.2.6 in /site (#2350) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) from 19.2.5 to 19.2.6.
Release notes

Sourced from react-dom's releases.

19.2.6 (May 6th, 2026)

React Server Components

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 10 +++++----- site/package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 1552ab67f3..ef64a45bb9 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -19,7 +19,7 @@ "micromatch": "^4.0.8", "prism-react-renderer": "^2.4.1", "react": "^18.3.1", - "react-dom": "^19.2.5", + "react-dom": "^19.2.6", "sharp": "^0.33.5" }, "devDependencies": { @@ -16061,15 +16061,15 @@ } }, "node_modules/react-dom": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", - "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.5" + "react": "^19.2.6" } }, "node_modules/react-fast-compare": { diff --git a/site/package.json b/site/package.json index 8f359d4348..07ea860566 100644 --- a/site/package.json +++ b/site/package.json @@ -25,7 +25,7 @@ "micromatch": "^4.0.8", "prism-react-renderer": "^2.4.1", "react": "^18.3.1", - "react-dom": "^19.2.5", + "react-dom": "^19.2.6", "sharp": "^0.33.5" }, "devDependencies": { From 2e219952e24e408102fc1048ec9207d1606b58e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 13:49:59 +0000 Subject: [PATCH 410/448] deps: bump react and @types/react in /site (#2352) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). These dependencies needed to be updated together. Updates `react` from 18.3.1 to 19.2.5
Release notes

Sourced from react's releases.

19.2.5 (April 8th, 2026)

React Server Components

19.2.4 (January 26th, 2026)

React Server Components

19.2.3 (December 11th, 2025)

React Server Components

19.2.2 (December 11th, 2025)

React Server Components

19.2.1 (December 3rd, 2025)

React Server Components

19.2.0 (Oct 1, 2025)

Below is a list of all new features, APIs, and bug fixes.

Read the React 19.2 release post for more information.

New React Features

  • <Activity>: A new API to hide and restore the UI and internal state of its children.
  • useEffectEvent is a React Hook that lets you extract non-reactive logic into an Effect Event.
  • cacheSignal (for RSCs) lets your know when the cache() lifetime is over.
  • React Performance tracks appear on the Performance panel’s timeline in your browser developer tools

New React DOM Features

  • Added resume APIs for partial pre-rendering with Web Streams:
  • Added resume APIs for partial pre-rendering with Node Streams:
  • Updated prerender APIs to return a postponed state that can be passed to the resume APIs.

Notable changes

  • React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming <ViewTransition> Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.

... (truncated)

Changelog

Sourced from react's changelog.

19.2.1 (Dec 3, 2025)

React Server Components

19.2.0 (October 1st, 2025)

Below is a list of all new features, APIs, and bug fixes.

Read the React 19.2 release post for more information.

New React Features

  • <Activity>: A new API to hide and restore the UI and internal state of its children.
  • useEffectEvent is a React Hook that lets you extract non-reactive logic into an Effect Event.
  • cacheSignal (for RSCs) lets your know when the cache() lifetime is over.
  • React Performance tracks appear on the Performance panel’s timeline in your browser developer tools

New React DOM Features

  • Added resume APIs for partial pre-rendering with Web Streams:
  • Added resume APIs for partial pre-rendering with Node Streams:
  • Updated prerender APIs to return a postponed state that can be passed to the resume APIs.

Notable changes

  • React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming <ViewTransition> Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.
  • Add Node Web Streams (prerender, renderToReadableStream) to server-side-rendering APIs for Node.js
  • Use underscore instead of : IDs generated by useId

All Changes

React

... (truncated)

Commits

Updates `@types/react` from 18.3.28 to 19.2.14
Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 1467 ++++++++++++++++++++++++++++------------ site/package.json | 4 +- 2 files changed, 1021 insertions(+), 450 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index ef64a45bb9..df2813bd01 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -13,12 +13,12 @@ "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", - "@types/react": "^18.3.28", + "@types/react": "^19.2.14", "clsx": "^2.1.1", "docusaurus-lunr-search": "^3.6.0", "micromatch": "^4.0.8", "prism-react-renderer": "^2.4.1", - "react": "^18.3.1", + "react": "^19.2.5", "react-dom": "^19.2.6", "sharp": "^0.33.5" }, @@ -1975,6 +1975,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" @@ -3566,20 +3567,6 @@ } } }, - "node_modules/@docusaurus/core/node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@docusaurus/cssnano-preset": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", @@ -4210,6 +4197,20 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/types/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@docusaurus/utils": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", @@ -4739,9 +4740,9 @@ } }, "node_modules/@jsonjoy.com/buffers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.0.tgz", - "integrity": "sha512-6RX+W5a+ZUY/c/7J5s5jK9UinLfJo5oWKh84fb4X0yK2q4WXEWUWZWuEMjvCb1YNUQhEAhUfr5scEGOH7jC4YQ==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4770,10 +4771,273 @@ "tslib": "2" } }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz", + "integrity": "sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz", + "integrity": "sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz", + "integrity": "sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz", + "integrity": "sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz", + "integrity": "sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz", + "integrity": "sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz", + "integrity": "sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.57.2", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz", + "integrity": "sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@jsonjoy.com/json-pack": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.20.0.tgz", - "integrity": "sha512-adcXFVorSQULtT4XDL0giRLr2EVGIcyWm6eQKZWTrRA4EEydGOY8QVQtL0PaITQpUyu+lOd/QOicw6vdy1v8QQ==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/base64": "^1.1.2", @@ -4782,8 +5046,25 @@ "@jsonjoy.com/json-pointer": "^1.0.2", "@jsonjoy.com/util": "^1.9.0", "hyperdyperid": "^1.2.0", - "thingies": "^2.5.0" + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "license": "Apache-2.0", "engines": { "node": ">=10.0" }, @@ -4835,6 +5116,22 @@ "tslib": "2" } }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", @@ -4895,6 +5192,18 @@ "react": ">=16" } }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4927,13 +5236,171 @@ "fastq": "^1.6.0" }, "engines": { - "node": ">= 8" + "node": ">= 8" + } + }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.7.0.tgz", + "integrity": "sha512-hew63shtzzvBcSHbhm+cyAmKe6AIfinT9hzEqSPjDC6opTTMKmTkQ0gHuN2KsWlvqiKw1S/fS94fhag/FJkioQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "@peculiar/asn1-x509-attr": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.7.0.tgz", + "integrity": "sha512-VVsAyGqErT9D1SY4aEqozThXMVI+ssVRiv2DDeYuvpBKLIgZ3hYs3Ay3u/VSoKq6ESFi9cf6rf3IOOzfwh7oMA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.7.0.tgz", + "integrity": "sha512-n7KEs/Q/wrB415cxy4fHOBhegp4NdJ15fkJPwcB/3/8iNBQC2L/N7SChJPKDJPZGYH0jD4Tg4/0vnHmwghnbKw==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.7.0.tgz", + "integrity": "sha512-V/nrlQVmhg7lYAsM7E13UDL5erAwFv6kCIVFqNaMIHSVi7dngcT839JkRTkQBqznMG98l2XjxYk74ZztAohZzA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.7.0", + "@peculiar/asn1-pkcs8": "^2.7.0", + "@peculiar/asn1-rsa": "^2.7.0", + "@peculiar/asn1-schema": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.7.0.tgz", + "integrity": "sha512-9GTl1nE8Mx1kTZ+7QyYatDyKsm34QcWRBFkY1iPvWC3X4Dona5s/tlLiQsx5WzVdZqiMBZNYT0buyw4/vbhnjw==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.7.0.tgz", + "integrity": "sha512-Bh7m+OuIaSEllPQcSd9OSp93F4ROWH7sbITWV8MI+8dwsjE5111/87VxiWVvYFKyww3vp39geLv9ENqhwWHcew==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.7.0", + "@peculiar/asn1-pfx": "^2.7.0", + "@peculiar/asn1-pkcs8": "^2.7.0", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "@peculiar/asn1-x509-attr": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.7.0.tgz", + "integrity": "sha512-/qvENQrXyTZURjMqSeofHul0JJt2sNSzSwk36pl2olkHbaioMQgrASDZAlHXl0xUlnVbHj0uGgOrBMTb5x2aJQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.7.0.tgz", + "integrity": "sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg==", + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.7.0.tgz", + "integrity": "sha512-mUn9RRrkGDnG4ALfunDmzyRW5dg+sWCj/pfnCCqEHYbkGxEpvUt6iVJv8Yw1cyp6SWZ26ZE5oSmI5SqEaen15g==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.7.0.tgz", + "integrity": "sha512-NS8e7SOgXipkzUPLF/sce7ukpMpWjhxYsH0n6Y+bHYo4TTxOb95Zv7hqwSuL212mj5YxovjdOKQOgH1As3E94w==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", + "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + }, + "engines": { + "node": ">=20.0.0" } }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "license": "MIT", "engines": { "node": ">=12.22.0" } @@ -4942,6 +5409,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "license": "MIT", "dependencies": { "graceful-fs": "4.2.10" }, @@ -4952,12 +5420,14 @@ "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "license": "ISC" }, "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.2.tgz", + "integrity": "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==", + "license": "MIT", "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", @@ -4968,9 +5438,9 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "license": "MIT" }, "node_modules/@sideway/address": { @@ -5284,6 +5754,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -5374,21 +5845,21 @@ } }, "node_modules/@types/express": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", - "@types/serve-static": "*" + "@types/serve-static": "^1" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", - "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -5420,12 +5891,14 @@ "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "license": "MIT" }, "node_modules/@types/http-errors": { "version": "2.0.5", @@ -5434,9 +5907,9 @@ "license": "MIT" }, "node_modules/@types/http-proxy": { - "version": "1.17.16", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", - "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5505,15 +5978,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/node-forge": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", - "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/parse5": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", @@ -5525,15 +5989,10 @@ "integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==", "license": "MIT" }, - "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" - }, "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", "license": "MIT" }, "node_modules/@types/range-parser": { @@ -5543,12 +6002,11 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", - "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.2.2" } }, @@ -5575,6 +6033,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "license": "MIT", "dependencies": { "@types/history": "^4.7.11", "@types/react": "*", @@ -5597,9 +6056,9 @@ } }, "node_modules/@types/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.0.tgz", - "integrity": "sha512-zBF6vZJn1IaMpg3xUF25VK3gd3l8zwE0ZLRX7dsQyQi+jp4E8mMDJNGDYnYse+bQhYwWERTxVwHpi3dMOq7RKQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5615,9 +6074,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.9.tgz", - "integrity": "sha512-dOTIuqpWLyl3BBXU3maNQsS4A3zuuoYRNIvYSxxhebPfXg2mzWQEPne/nlJ37yOse6uGgR386uTpdsx4D0QZWA==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "license": "MIT", "dependencies": { "@types/http-errors": "*", @@ -5626,9 +6085,9 @@ } }, "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "license": "MIT", "dependencies": { "@types/mime": "^1", @@ -5920,9 +6379,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -5935,6 +6394,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -6038,6 +6498,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", "dependencies": { "string-width": "^4.1.0" } @@ -6045,12 +6506,14 @@ "node_modules/ansi-align/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/ansi-align/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6148,6 +6611,20 @@ "node": ">=8" } }, + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/astring": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", @@ -6444,9 +6921,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -6457,7 +6934,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -6485,41 +6962,12 @@ "ms": "2.0.0" } }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/body-parser/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/bonjour-service": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", @@ -6539,6 +6987,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^6.2.0", @@ -6662,10 +7111,20 @@ "node": ">= 0.8" } }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "license": "MIT", "engines": { "node": ">=14.16" } @@ -6674,6 +7133,7 @@ "version": "10.2.14", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "license": "MIT", "dependencies": { "@types/http-cache-semantics": "^4.0.2", "get-stream": "^6.0.1", @@ -6687,28 +7147,6 @@ "node": ">=14.16" } }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", @@ -6769,6 +7207,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" @@ -6976,6 +7415,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -6984,6 +7424,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", "dependencies": { "source-map": "~0.6.0" }, @@ -6995,6 +7436,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -7012,6 +7454,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -7020,9 +7463,10 @@ } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -7036,12 +7480,14 @@ "node_modules/cli-table3/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/cli-table3/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7255,6 +7701,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -7264,6 +7711,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "license": "BSD-2-Clause", "dependencies": { "dot-prop": "^6.0.1", "graceful-fs": "^4.2.6", @@ -7326,18 +7774,18 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, "node_modules/copy-text-to-clipboard": { @@ -7420,10 +7868,11 @@ } }, "node_modules/core-js": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.34.0.tgz", - "integrity": "sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", "hasInstallScript": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -7491,6 +7940,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "license": "MIT", "dependencies": { "type-fest": "^1.0.1" }, @@ -7505,6 +7955,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -8012,9 +8463,9 @@ } }, "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -8028,9 +8479,9 @@ } }, "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", "license": "MIT", "engines": { "node": ">=18" @@ -8043,6 +8494,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", "engines": { "node": ">=10" } @@ -8133,9 +8585,10 @@ "license": "MIT" }, "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "license": "MIT", "dependencies": { "address": "^1.0.1", "debug": "4" @@ -8143,6 +8596,9 @@ "bin": { "detect": "bin/detect-port.js", "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" } }, "node_modules/devlop": { @@ -8325,6 +8781,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", "dependencies": { "utila": "~0.4" } @@ -8396,6 +8853,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -8410,6 +8868,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "license": "MIT", "engines": { "node": ">=8" } @@ -8431,12 +8890,14 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", @@ -8453,7 +8914,8 @@ "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" }, "node_modules/emojilib": { "version": "2.4.0", @@ -8611,6 +9073,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -8867,18 +9330,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -8888,14 +9339,14 @@ } }, "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "~1.20.3", + "body-parser": "~1.20.5", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", @@ -8914,7 +9365,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "~6.14.0", + "qs": "~6.15.1", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", @@ -9168,17 +9619,17 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -9260,6 +9711,15 @@ } } }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -9430,6 +9890,18 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -9479,6 +9951,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "license": "MIT", "dependencies": { "ini": "2.0.0" }, @@ -9493,6 +9966,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", "engines": { "node": ">=10" } @@ -9529,6 +10003,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -9575,6 +10086,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", "dependencies": { "duplexer": "^0.1.2" }, @@ -9632,6 +10144,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -9972,6 +10485,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", "bin": { "he": "bin/he" } @@ -10097,6 +10611,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -10115,9 +10630,10 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz", + "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==", + "license": "MIT", "dependencies": { "@types/html-minifier-terser": "^6.0.0", "html-minifier-terser": "^6.0.2", @@ -10149,6 +10665,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", "engines": { "node": ">= 12" } @@ -10157,6 +10674,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "license": "MIT", "dependencies": { "camel-case": "^4.1.2", "clean-css": "^5.2.2", @@ -10193,9 +10711,10 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" }, "node_modules/http-deceiver": { "version": "1.2.7", @@ -10204,19 +10723,23 @@ "license": "MIT" }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/http-parser-js": { @@ -10279,6 +10802,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -10393,6 +10917,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "license": "MIT", "engines": { "node": ">=8" } @@ -10401,6 +10926,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -10449,9 +10975,9 @@ } }, "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", "license": "MIT", "engines": { "node": ">= 10" @@ -10525,6 +11051,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -10657,6 +11184,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "license": "MIT", "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" @@ -10669,9 +11197,9 @@ } }, "node_modules/is-network-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", - "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz", + "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==", "license": "MIT", "engines": { "node": ">=16" @@ -10681,9 +11209,10 @@ } }, "node_modules/is-npm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.1.0.tgz", + "integrity": "sha512-O2z4/kNgyjhQwVR1Wpkbfc19JIhggF97NZNCpWTnjH7kVcZMUrnut9XSN7txI7VdyIYk5ZatOq3zvSuWpU8hoA==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -10712,6 +11241,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -10752,7 +11282,8 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" }, "node_modules/is-wsl": { "version": "2.2.0", @@ -10770,6 +11301,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "license": "MIT", "engines": { "node": ">=12" } @@ -10893,7 +11425,8 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -10932,6 +11465,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -10956,6 +11490,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "license": "MIT", "dependencies": { "package-json": "^8.1.0" }, @@ -10967,9 +11502,9 @@ } }, "node_modules/launch-editor": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz", - "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz", + "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==", "license": "MIT", "dependencies": { "picocolors": "^1.1.1", @@ -10980,6 +11515,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -11100,6 +11636,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -11580,11 +12117,19 @@ } }, "node_modules/memfs": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.49.0.tgz", - "integrity": "sha512-L9uC9vGuc4xFybbdOpRLoOAOq1YEBBsocCs5NVW32DfU+CZWWIn3OVF+lB8Gp4ttBVSMazwrTrjv8ussX/e3VQ==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz", + "integrity": "sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==", "license": "Apache-2.0", "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-to-fsa": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", @@ -11595,6 +12140,9 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, "node_modules/merge-descriptors": { @@ -13472,6 +14020,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -13540,9 +14089,9 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "license": "MIT", "engines": { "node": ">=10" @@ -13644,15 +14193,6 @@ "node": ">=18" } }, - "node_modules/node-forge": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", - "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-releases": { "version": "2.0.44", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", @@ -13682,6 +14222,18 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/not": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz", @@ -13910,6 +14462,15 @@ "opener": "bin/opener-bin.js" } }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -14013,6 +14574,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "license": "MIT", "dependencies": { "got": "^12.1.0", "registry-auth-token": "^5.0.1", @@ -14026,77 +14588,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json/node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/package-json/node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "license": "MIT", - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/package-json/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json/node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/package-json/node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -14213,6 +14709,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -14297,6 +14794,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/postcss": { "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", @@ -15785,6 +16299,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", "dependencies": { "lodash": "^4.17.20", "renderkid": "^3.0.0" @@ -15862,7 +16377,8 @@ "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -15905,9 +16421,10 @@ } }, "node_modules/pupa": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.3.0.tgz", + "integrity": "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==", + "license": "MIT", "dependencies": { "escape-goat": "^4.0.0" }, @@ -15918,10 +16435,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -15957,6 +16492,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -15997,35 +16533,6 @@ "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/raw-body/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -16049,13 +16556,10 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } @@ -16165,6 +16669,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.1.2" }, @@ -16282,6 +16787,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -16323,11 +16834,12 @@ } }, "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", + "license": "MIT", "dependencies": { - "@pnpm/npm-conf": "^2.1.0" + "@pnpm/npm-conf": "^3.0.2" }, "engines": { "node": ">=14" @@ -16337,6 +16849,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "license": "MIT", "dependencies": { "rc": "1.2.8" }, @@ -16560,6 +17073,7 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -16696,6 +17210,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", "dependencies": { "css-select": "^4.1.3", "dom-converter": "^0.2.0", @@ -16708,6 +17223,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", @@ -16723,6 +17239,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -16736,6 +17253,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.2.0" }, @@ -16750,6 +17268,7 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -16763,6 +17282,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -16778,6 +17298,7 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.0.0", @@ -16839,7 +17360,8 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", @@ -16859,6 +17381,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "license": "MIT", "dependencies": { "lowercase-keys": "^3.0.0" }, @@ -17033,16 +17556,16 @@ "license": "MIT" }, "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", + "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==", "license": "MIT", "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" + "@peculiar/x509": "^1.14.2", + "pkijs": "^3.3.3" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/semver": { @@ -17060,6 +17583,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -17071,24 +17595,24 @@ } }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -17109,15 +17633,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/send/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -17158,21 +17673,25 @@ "license": "MIT" }, "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", "license": "MIT", "dependencies": { - "accepts": "~1.3.4", + "accepts": "~1.3.8", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" }, "engines": { "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/serve-index/node_modules/debug": { @@ -17194,25 +17713,41 @@ } }, "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "license": "MIT", "dependencies": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "license": "ISC" + "node_modules/serve-index/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", @@ -17220,12 +17755,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "license": "ISC" - }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -17236,15 +17765,15 @@ } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.19.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -17379,13 +17908,13 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -17681,9 +18210,9 @@ } }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -17720,6 +18249,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -17733,9 +18263,10 @@ } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -17744,11 +18275,12 @@ } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -18069,9 +18601,9 @@ } }, "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", "license": "MIT", "engines": { "node": ">=10.18" @@ -18101,9 +18633,9 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, "node_modules/tinypool": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" @@ -18233,9 +18765,28 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -18252,6 +18803,7 @@ "version": "2.19.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -18297,6 +18849,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } @@ -18392,6 +18945,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "license": "MIT", "dependencies": { "crypto-random-string": "^4.0.0" }, @@ -18555,6 +19109,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "license": "BSD-2-Clause", "dependencies": { "boxen": "^7.0.0", "chalk": "^5.0.1", @@ -18582,6 +19137,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^7.0.1", @@ -18603,6 +19159,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -18611,9 +19168,10 @@ } }, "node_modules/update-notifier/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -18735,7 +19293,8 @@ "node_modules/utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "license": "MIT" }, "node_modules/utility-types": { "version": "3.11.0", @@ -18759,6 +19318,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -18974,15 +19534,19 @@ } }, "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/webpack-dev-middleware/node_modules/range-parser": { @@ -18995,14 +19559,14 @@ } }, "node_modules/webpack-dev-server": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", - "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.4.tgz", + "integrity": "sha512-GqDPGZN9bRqKBTkp4aWkobDDHMsrXKoGSdOH56smIri8qR0JG8gfL8/v/f/OZR3/OKXjG8uwJbFVhKm/FNU/UA==", "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", + "@types/express": "^4.17.25", "@types/express-serve-static-core": "^4.17.21", "@types/serve-index": "^1.9.4", "@types/serve-static": "^1.15.5", @@ -19012,9 +19576,9 @@ "bonjour-service": "^1.2.1", "chokidar": "^3.6.0", "colorette": "^2.0.10", - "compression": "^1.7.4", + "compression": "^1.8.1", "connect-history-api-fallback": "^2.0.0", - "express": "^4.21.2", + "express": "^4.22.1", "graceful-fs": "^4.2.6", "http-proxy-middleware": "^2.0.9", "ipaddr.js": "^2.1.0", @@ -19022,7 +19586,7 @@ "open": "^10.0.3", "p-retry": "^6.2.0", "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", + "selfsigned": "^5.5.0", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", @@ -19082,9 +19646,9 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -19103,17 +19667,17 @@ } }, "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", - "wildcard": "^2.0.0" + "wildcard": "^2.0.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" } }, "node_modules/webpack-sources": { @@ -19238,6 +19802,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "license": "MIT", "dependencies": { "string-width": "^5.0.1" }, @@ -19257,6 +19822,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -19270,9 +19836,10 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -19281,9 +19848,10 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -19292,11 +19860,12 @@ } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -19314,6 +19883,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -19358,9 +19928,9 @@ } }, "node_modules/wsl-utils/node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -19376,6 +19946,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", "engines": { "node": ">=12" }, diff --git a/site/package.json b/site/package.json index 07ea860566..e6ed8fcf5a 100644 --- a/site/package.json +++ b/site/package.json @@ -19,12 +19,12 @@ "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", - "@types/react": "^18.3.28", + "@types/react": "^19.2.14", "clsx": "^2.1.1", "docusaurus-lunr-search": "^3.6.0", "micromatch": "^4.0.8", "prism-react-renderer": "^2.4.1", - "react": "^18.3.1", + "react": "^19.2.5", "react-dom": "^19.2.6", "sharp": "^0.33.5" }, From 7dff88582b044898c12c38d703a03b57abf38599 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 14:58:12 +0000 Subject: [PATCH 411/448] deps: bump sharp from 0.33.5 to 0.34.5 in /site (#2338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sharp](https://github.com/lovell/sharp) from 0.33.5 to 0.34.5.
Release notes

Sourced from sharp's releases.

v0.34.5

  • Upgrade to libvips v8.17.3 for upstream bug fixes.

  • Add experimental support for prebuilt Linux RISC-V 64-bit binaries.

  • Support building from source with npm v12+, deprecate --build-from-source flag. #4458

  • Add support for BigTIFF output. #4459 @​throwbi

  • Improve error messaging when only warnings issued. #4465

  • Simplify ICC processing when retaining input profiles. #4468

v0.34.5-rc.1

  • Upgrade to libvips v8.17.3 for upstream bug fixes.

  • Add experimental support for prebuilt Linux RISC-V 64-bit binaries.

  • Support building from source with npm v12+, deprecate --build-from-source flag. #4458

  • Add support for BigTIFF output. #4459 @​throwbi

  • Improve error messaging when only warnings issued. #4465

  • Simplify ICC processing when retaining input profiles. #4468

v0.34.5-rc.0

  • Upgrade to libvips v8.17.3 for upstream bug fixes.

  • Add experimental support for prebuilt Linux RISC-V 64-bit binaries.

  • Support building from source with npm v12+, deprecate --build-from-source flag. #4458

  • Add support for BigTIFF output. #4459 @​throwbi

  • Improve error messaging when only warnings issued. #4465

... (truncated)

Commits
  • e062456 Release v0.34.5
  • 6450c70 Prerelease v0.34.5-rc.1
  • f7c95d1 TypeScript: consolidate a few enum-like properties
  • ef86a75 Prerelease v0.34.5-rc.0
  • 6c1e840 Use structured binding for tuples where possible
  • e1628d8 Simplify ICC processing when retaining input profiles #4468
  • 4f9f817 Linter: apply all recommended biome settings
  • 09d5aa8 Docs: update internal and libvips doc links
  • 040b73c Upgrade to libvips v8.17.3
  • 1f2f33d Ensure licensing headers are retained by code bundlers
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for sharp since your current version.

Install script changes

This version modifies install script that runs during installation. Review the package contents before updating.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 334 ++++++++++++++++++++++++++++------------- site/package.json | 2 +- 2 files changed, 234 insertions(+), 102 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index df2813bd01..5553d7deec 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -20,7 +20,7 @@ "prism-react-renderer": "^2.4.1", "react": "^19.2.5", "react-dom": "^19.2.6", - "sharp": "^0.33.5" + "sharp": "^0.34.5" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", @@ -4276,9 +4276,10 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -4299,13 +4300,23 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -4317,16 +4328,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -4338,16 +4350,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -4357,12 +4370,13 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -4372,12 +4386,13 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", "cpu": [ "arm" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -4387,12 +4402,45 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -4402,12 +4450,13 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", "cpu": [ "s390x" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -4417,12 +4466,13 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -4432,12 +4482,13 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -4447,12 +4498,13 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -4462,12 +4514,13 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", "cpu": [ "arm" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4479,16 +4532,39 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-arm": "1.2.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", "cpu": [ "arm64" ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4500,16 +4576,39 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ "s390x" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4521,16 +4620,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4542,16 +4642,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-x64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4563,16 +4664,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4584,19 +4686,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ "wasm32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@emnapi/runtime": "^1.7.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -4605,13 +4708,33 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ "ia32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -4624,12 +4747,13 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", "cpu": [ "x64" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -8571,9 +8695,10 @@ } }, "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -17569,9 +17694,10 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -17820,14 +17946,15 @@ "license": "MIT" }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -17836,25 +17963,30 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, "node_modules/shebang-command": { diff --git a/site/package.json b/site/package.json index e6ed8fcf5a..a706708631 100644 --- a/site/package.json +++ b/site/package.json @@ -26,7 +26,7 @@ "prism-react-renderer": "^2.4.1", "react": "^19.2.5", "react-dom": "^19.2.6", - "sharp": "^0.33.5" + "sharp": "^0.34.5" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", From 2323dfbdd4605474dd69c6eb8e4568df4b4410dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 10:58:40 -0400 Subject: [PATCH 412/448] deps: bump helm.sh/helm/v3 from 3.20.2 to 3.21.0 (#2354) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.20.2 to 3.21.0.
Release notes

Sourced from helm.sh/helm/v3's releases.

Helm v3.21.0 is a feature release. Users are encouraged to upgrade for the best experience.

The community keeps growing, and we'd love to see you there!

  • Join the discussion in Kubernetes Slack:
    • for questions and just to hang out
    • for discussing PRs, code, and bugs
  • Hang out at the Public Developer Call: Thursday, 9:30 Pacific via Zoom
  • Test, debug, and contribute charts: ArtifactHub/packages

Notable Changes

  • Kubernetes client libraries to v1.36
  • notable changes here

Installation and Upgrading

Download Helm v3.21.0. The common platform binaries are here:

This release was signed by @​gjenkins8 with key BF88 8333 D96A 1C18 E268 2AAE D79D 67C9 EC01 6739, which can be found at https://keys.openpgp.org/vks/v1/by-fingerprint/BF888333D96A1C18E2682AAED79D67C9EC016739. Please use the attached signatures for verifying this release using gpg.

The Quickstart Guide will get you going from there. For upgrade instructions or detailed installation notes, check the install guide. You can also use a script to install on any system with bash.

What's Next

  • 3.21.1 will contain only bug fixes.
  • 3.22.0 is the next feature release for Kubernetes v1.37

Changelog

  • [v3] Bump to version v3.21 e0878d41b711792be60777fd65ad23a101e6b85f (George Jenkins)
  • fix: upgrade opentelemetry packages to patch CVEs 13d5fc4ae0e7222e1af8796ff4fa467b52208471 (Terry Howe)
  • fix: Chart dot-name path bug 2552884e3bc1b763c3901c5ea7240b59ef6791f1 (George Jenkins)
  • fix: pin codeql-action/upload-sarif to commit SHA in scorecards workflow ec05dd5f0481c2de3a41a554adf3c52a6a2a9bb6 (Terry Howe)
  • add image index test b0dfec5af4d7f642d8dea3b9058856541fe5017c (Pedro Tôrres)
  • fix pulling charts from OCI indices e629995c5d65ec2d5095ecd6d094bf85d02b3266 (Pedro Tôrres)
  • chore(deps): bump the k8s-io group with 7 updates 9c854fbd937ae0efe0e0a5063e7449d8973a85fd (dependabot[bot])
  • chore(deps): bump golang.org/x/crypto from 0.47.0 to 0.48.0 a692247486fb6893f00af65fdfb05da538c7b1d5 (dependabot[bot])

... (truncated)

Commits
  • e0878d4 [v3] Bump to version v3.21
  • 4d4902c Merge pull request #32041 from TerryHowe/fix/upgrade-otel-cves
  • 13d5fc4 fix: upgrade opentelemetry packages to patch CVEs
  • a60cb79 Merge commit from fork
  • d3bc853 Merge pull request #32026 from gjenkins8/gjenkins/code_action_pin_v3
  • 2552884 fix: Chart dot-name path bug
  • ec05dd5 fix: pin codeql-action/upload-sarif to commit SHA in scorecards workflow
  • 6d809b2 Merge pull request #31883 from t0rr3sp3dr0/pedrotorres/backport-31776-to-v3
  • b0dfec5 add image index test
  • e629995 fix pulling charts from OCI indices
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=helm.sh/helm/v3&package-manager=go_modules&previous-version=3.20.2&new-version=3.21.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 9 +-------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index 292125beb8..9dd38b2b53 100644 --- a/go.mod +++ b/go.mod @@ -261,7 +261,7 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 - helm.sh/helm/v3 v3.20.2 + helm.sh/helm/v3 v3.21.0 k8s.io/apiextensions-apiserver v0.35.3 k8s.io/cli-runtime v0.35.3 k8s.io/kubectl v0.35.3 @@ -653,14 +653,7 @@ require ( go.opentelemetry.io/contrib/detectors/gcp v1.42.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.65.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.16.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect diff --git a/go.sum b/go.sum index e64f4428b0..2701faaaa0 100644 --- a/go.sum +++ b/go.sum @@ -1634,14 +1634,14 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8V go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= 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/otlplog/otlploggrpc v0.16.0 h1:ZVg+kCXxd9LtAaQNKBxAvJ5NpMf7LpvEr4MIZqb0TMQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0/go.mod h1:hh0tMeZ75CCXrHd9OXRYxTlCAdxcXioWHFIpYw2rZu8= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0/go.mod h1:0Lr9vmGKzadCTgsiBydxr6GEZ8SsZ7Ks53LzjWG5Ar4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 h1:0NIXxOCFx+SKbhCVxwl3ETG8ClLPAa0KuKV6p3yhxP8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0/go.mod h1:ChZSJbbfbl/DcRZNc9Gqh6DYGlfjw4PvO1pEOZH1ZsE= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= 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/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= @@ -1650,20 +1650,20 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJK go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE= go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0 h1:k6KdfZk72tVW/QVZf60xlDziDvYAePj5QHwoQvrB2m8= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0/go.mod h1:5Y3ZJLqzi/x/kYtrSrPSx7TFI/SGsL7q2kME027tH6I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0 h1:6VjV6Et+1Hd2iLZEPtdV7vie80Yyqf7oikJLjQ/myi0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0/go.mod h1:u8hcp8ji5gaM/RfcOo8z9NMnf1pVLfVY7lBY2VOGuUU= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= -go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4= -go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 h1:GJkybS+crDMdExT/BUNCEgfrmfboztcS6PhvSo88HKM= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0/go.mod h1:NuAyxRYIG2lKX3YQkB+83StTxM7s52PUUkRRiC0wnYI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= 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/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI= -go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= 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= @@ -1982,8 +1982,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -helm.sh/helm/v3 v3.20.2 h1:binM4rvPx5DcNsa1sIt7UZi55lRbu3pZUFmQkSoRh48= -helm.sh/helm/v3 v3.20.2/go.mod h1:Fl1kBaWCpkUrM6IYXPjQ3bdZQfFrogKArqptvueZ6Ww= +helm.sh/helm/v3 v3.21.0 h1:9TRbaXQH+BIKLLDYlu++JsyWodS5kBBOLF7C7HY5+cs= +helm.sh/helm/v3 v3.21.0/go.mod h1:5IvU6Ae6ruB/vasVHhnC1IU5RvqFM349vLYS1BiHqeY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= From fc96a0c55c0a568d0403637383684437ed24e3ce Mon Sep 17 00:00:00 2001 From: Mereta Date: Thu, 14 May 2026 17:31:23 +0100 Subject: [PATCH 413/448] deps(golang): Bump GoLang (#2355) # Description Bumping base image GoLang Version. Previous Release `v1.2.0`: image Latest with Go Bump: (even with Hubble bump to `v1.19.3` we still have 9 CVE's. image ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: mereta --- cli/Dockerfile | 4 ++-- controller/Dockerfile | 4 ++-- controller/Dockerfile.gogen | 4 ++-- controller/Dockerfile.proto | 4 ++-- controller/Dockerfile.windows-cgo | 4 ++-- controller/Dockerfile.windows-native | 4 ++-- hack/tools/kapinger/Dockerfile | 8 ++++---- hack/tools/toolbox/Dockerfile | 4 ++-- operator/Dockerfile | 4 ++-- operator/Dockerfile.windows-2022 | 4 ++-- test/image/Dockerfile | 4 ++-- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 98d47ded9c..e4febdd144 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index e62c6880aa..86ba5ae443 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS golang +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:9230290079612a2a8d30a0aa8b8f097c3194e787d09987df0c3e6b8f6271ee27 AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index fe20303bf1..aebe3c43ce 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 8f0f930218..77d478c65e 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 7d133022de..87172128b2 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:58d69eaa704978128e3ff640db70412786a5100be4999e46c5670bdeea5fb320 AS cgo +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:22617ad636077ab971853e1b61ff610cde773d3e6e1a10075fe7c4fdfde1f1b1 AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index fc06fc38c7..c2f67e42c4 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -3,8 +3,8 @@ # buildx targets, and this one requires legacy build. # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:58d69eaa704978128e3ff640db70412786a5100be4999e46c5670bdeea5fb320 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:22617ad636077ab971853e1b61ff610cde773d3e6e1a10075fe7c4fdfde1f1b1 AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index c530d9e06b..ab33c2b97c 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:61e607875d60ae21a7a4a49110fe7098355473fbc74ab13091e3c1160cc92f18 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3@sha256:9cb93c7fc65fcec28b0af140bd4e42510e7553dd67718289dfee2a955986b7e3 AS builder WORKDIR /build ADD . . @@ -16,8 +16,8 @@ COPY --from=builder /build/kapinger . CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:61e607875d60ae21a7a4a49110fe7098355473fbc74ab13091e3c1160cc92f18 AS windows-builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3@sha256:9cb93c7fc65fcec28b0af140bd4e42510e7553dd67718289dfee2a955986b7e3 AS windows-builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index ae7e35b662..0aea90b01c 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2@sha256:61e607875d60ae21a7a4a49110fe7098355473fbc74ab13091e3c1160cc92f18 AS build +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3@sha256:9cb93c7fc65fcec28b0af140bd4e42510e7553dd67718289dfee2a955986b7e3 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 69b773df8e..f9d0e1de1f 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index 92e87f37a7..bbc6fa5559 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:6b48a8fb2ae39953f6a01a4077eae21c759635babb41ca458d364610af626666 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index f2676c5151..f54716ec0a 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage -# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.2-azurelinux3.0@sha256:257614fe59a6e7fb56909eec9a59a6d0d0794a331ebc1d6dc93aa8ef995d34f5 AS builder +# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 3d7876663b034313c4e8d6b6d44602e3191b50df Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Thu, 14 May 2026 12:40:24 -0400 Subject: [PATCH 414/448] fix(deps): drop dependabot group-by directive (upstream bug) (#2348) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description The `group-by: dependency-name` directive added to all four Docker family groups in #2306 turns out to be broken by two open upstream bugs in `dependabot/dependabot-core`: - [#14780](https://github.com/dependabot/dependabot-core/issues/14780) — PRs created with `group-by: dependency-name` can't be rebased; every `@dependabot rebase` returns "unknown group has been removed from your config" and the PR is permanently stuck. - [#14286](https://github.com/dependabot/dependabot-core/issues/14286) — `group-by: dependency-name` produces one PR per dependency rather than a single grouped PR, defeating the consolidation goal entirely. In practice this caused every per-directory Docker bump after #2306 to fail with `unknown_error` (seen in run [25821608265](https://github.com/microsoft/retina/actions/runs/25821608265)) and forced manual closure of ~12 stuck PRs. Drop the directive on all four Docker groups. The `patterns:` definitions stay, so per-directory grouping still applies and per-image PRs continue to land as before #2306. ## Related Issue Reverts the `group-by` addition from #2306. No closing trailer — #2306's other change (dropping invalid `cooldown.semver-major-days`) is preserved. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed N/A — config-only change. Behavior reverts to the pre-#2306 baseline, which was already running cleanly. ## Additional Notes N/A. Signed-off-by: Quang Nguyen --- .github/dependabot.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 6a6d9df620..1e471c9bcd 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -23,16 +23,12 @@ updates: groups: golang-base: patterns: ["*golang*"] - group-by: "dependency-name" azurelinux-base: patterns: ["*azurelinux*"] - group-by: "dependency-name" windows-base: patterns: ["*windows*", "*nanoserver*", "*servercore*"] - group-by: "dependency-name" ubuntu-base: patterns: ["*ubuntu*"] - group-by: "dependency-name" # GitHub Actions - package-ecosystem: "github-actions" From f26239f7bd9f69259127e3226b1907185e872bc9 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 14 May 2026 23:34:15 +0100 Subject: [PATCH 415/448] fix: update scale test sku (#2357) # Description Please provide a brief description of the changes made in this pull request. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- test/e2e/framework/azure/skus.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/framework/azure/skus.go b/test/e2e/framework/azure/skus.go index d2885f63f3..c8ab35a260 100644 --- a/test/e2e/framework/azure/skus.go +++ b/test/e2e/framework/azure/skus.go @@ -3,7 +3,7 @@ package azure import "os" var ( - AgentLinuxSKU = skuFromEnv("AZURE_AGENT_LINUX_SKU", "Standard_D4ds_v4") + AgentLinuxSKU = skuFromEnv("AZURE_AGENT_LINUX_SKU", "Standard_D4ds_v3") AgentLinuxARMSKU = skuFromEnv("AZURE_AGENT_LINUX_ARM_SKU", "Standard_D4pds_v5") AgentWindowsSKU = skuFromEnv("AZURE_AGENT_WINDOWS_SKU", "Standard_D4ds_v4") ) From c1ac917faea3db406770b0d6333844e9d1e494b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 18:34:29 -0400 Subject: [PATCH 416/448] deps: bump typescript from 6.0.2 to 6.0.3 in /site (#2353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [typescript](https://github.com/microsoft/TypeScript) from 6.0.2 to 6.0.3.
Release notes

Sourced from typescript's releases.

TypeScript 6.0.3

For release notes, check out the release announcement blog post.

Downloads are available on:

Commits
  • 050880c Bump version to 6.0.3 and LKG
  • eeae9dd 🤖 Pick PR #63401 (Also check package name validity in...) into release-6.0 (#...
  • ad1c695 🤖 Pick PR #63368 (Harden ATA package name filtering) into release-6.0 (#63372)
  • 0725fb4 🤖 Pick PR #63310 (Mark class property initializers as...) into release-6.0 (#...
  • See full diff in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 8 ++++---- site/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 5553d7deec..059b613e12 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -28,7 +28,7 @@ "@docusaurus/types": "^3.10.1", "css-loader": "^7.1.2", "style-loader": "^4.0.0", - "typescript": "^6.0.2" + "typescript": "^6.0.3" }, "engines": { "node": ">=18.0.0" @@ -18987,9 +18987,9 @@ } }, "node_modules/typescript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", - "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "devOptional": true, "license": "Apache-2.0", "bin": { diff --git a/site/package.json b/site/package.json index a706708631..aea0436cd5 100644 --- a/site/package.json +++ b/site/package.json @@ -34,7 +34,7 @@ "@docusaurus/types": "^3.10.1", "css-loader": "^7.1.2", "style-loader": "^4.0.0", - "typescript": "^6.0.2" + "typescript": "^6.0.3" }, "browserslist": { "production": [ From e2027fd0d7072c557fe871e138a17a4e57c6e701 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 21:29:09 -0400 Subject: [PATCH 417/448] deps: Bump css-loader from 7.1.2 to 7.1.4 in /site (#2346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [css-loader](https://github.com/webpack/css-loader) from 7.1.2 to 7.1.4.
Release notes

Sourced from css-loader's releases.

v7.1.4

7.1.4 (2026-02-16)

Bug Fixes

  • update peer dependency for @​rspack/core v2 (#1652) (aeddefe)

v7.1.3

7.1.3 (2026-01-27)

Bug Fixes

Changelog

Sourced from css-loader's changelog.

7.1.4 (2026-02-16)

Bug Fixes

  • update peer dependency for @​rspack/core v2 (#1652) (aeddefe)

7.1.3 (2026-01-27)

Bug Fixes

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 15 ++++++++------- site/package.json | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 059b613e12..b7b356c0ff 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -26,7 +26,7 @@ "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.10.1", "@docusaurus/types": "^3.10.1", - "css-loader": "^7.1.2", + "css-loader": "^7.1.4", "style-loader": "^4.0.0", "typescript": "^6.0.3" }, @@ -8200,19 +8200,20 @@ } }, "node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.4.tgz", + "integrity": "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==", "dev": true, + "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.33", + "postcss": "^8.4.40", "postcss-modules-extract-imports": "^3.1.0", "postcss-modules-local-by-default": "^4.0.5", "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "semver": "^7.6.3" }, "engines": { "node": ">= 18.12.0" @@ -8222,7 +8223,7 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", "webpack": "^5.27.0" }, "peerDependenciesMeta": { diff --git a/site/package.json b/site/package.json index aea0436cd5..e72301530c 100644 --- a/site/package.json +++ b/site/package.json @@ -32,7 +32,7 @@ "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.10.1", "@docusaurus/types": "^3.10.1", - "css-loader": "^7.1.2", + "css-loader": "^7.1.4", "style-loader": "^4.0.0", "typescript": "^6.0.3" }, From d2a57d010c9e22a2e04ef23a88d7388ec203e9a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 21:29:29 -0400 Subject: [PATCH 418/448] deps: bump github.com/slack-go/slack from 0.13.0 to 0.23.1 (#2361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/slack-go/slack](https://github.com/slack-go/slack) from 0.13.0 to 0.23.1.
Release notes

Sourced from github.com/slack-go/slack's releases.

v0.23.1

[!IMPORTANT] Even though this is a [security] patch release, if you were using an empty secret, this is a breaking change due to a change in behaviour. That's on purpose, to ensure you fix your approach so that there are no footguns.

Fixed

  • NewSecretsVerifier now rejects empty signing secrets to avoid accepting forged request signatures when applications are misconfigured.

Full Changelog: https://github.com/slack-go/slack/compare/v0.23.0...v0.23.1

v0.23.0

Added

New Contributors

Full Changelog: https://github.com/slack-go/slack/compare/v0.22.0...v0.23.0

v0.22.0

What's Changed

Added

  • OAuth PKCE support - OAuthOptionCodeVerifier option for GetOAuthV2Response, plus GenerateCodeVerifier() and GenerateCodeChallenge() helpers (RFC 7636). client_secret is now conditionally omitted when empty in both GetOAuthV2ResponseContext and RefreshOAuthV2TokenContext.
  • Manifest scope fields - BotOptional and UserOptional on OAuthScopes.
  • Rich text styles - Underline, Highlight, ClientHighlight, and Unlink on RichTextSectionTextStyle. Style field on RichTextSectionUserGroupElement.
  • Assistant search context - Sort, SortDir, Before, After, Highlight, IncludeContextMessages, IncludeDeletedUsers, IncludeMessageBlocks, IncludeArchivedChannels, DisableSemanticSearch, Modifiers, TermClauses parameters and new response types (AssistantSearchContextFile, AssistantSearchContextChannel, AssistantSearchContextMessageContext).

Fixed

  • socketmode: malformed JSON no longer forces reconnect - json.SyntaxError and json.UnmarshalTypeError now emit an EventTypeIncomingError event and continue reading instead of killing the WebSocket connection.
  • socketmode: debug_reconnects query param applied correctly - the parameter was silently discarded due to a missing url.RawQuery assignment.
  • ChannelTypes and ContentTypes now send comma-separated values instead of repeated form keys, matching the convention used by every other method in the library.

Docs

  • assistant:write scope marked as deprecated in favour of chat:write.

Full Changelog: v0.21.1...v0.22.0

v0.21.1

Added

  • MessageEvent channel type helpers — New ChannelTypeChannel, ChannelTypeGroup,

... (truncated)

Changelog

Sourced from github.com/slack-go/slack's changelog.

[0.23.1] - 2026-05-10

Fixed

  • NewSecretsVerifier now rejects empty signing secrets to avoid accepting forged request signatures when applications are misconfigured.

[0.23.0] - 2026-04-22

Added

  • Block Kit: CardBlock and CarouselBlock — Support for two of the new agent-UI blocks announced in the April 16 Slack changelog. CardBlock is constructed via NewCardBlock with a functional-options pattern and fluent With* builders (WithTitle, WithSubtitle, WithBody, WithIcon, WithHeroImage, WithActions). CarouselBlock is constructed via NewCarouselBlock with a variadic *CardBlock list plus WithBlockID and AddCard helpers. Both blocks wire into Blocks.UnmarshalJSON for round-trip fidelity, and reuse existing ImageBlockElement / ButtonBlockElement / BlockElements types rather than introducing new composition objects.
  • Block Kit: AlertBlock — Support for the third of the new agent-UI blocks from the April 16 Slack changelog. AlertBlock is constructed via NewAlertBlock with a *TextBlockObject body and a functional-options pattern. Severity is set via AlertBlockOptionLevel (AlertLevelDefault, AlertLevelInfo, AlertLevelWarning, AlertLevelError, AlertLevelSuccess) and the block ID via AlertBlockOptionBlockID. Wires into Blocks.UnmarshalJSON for round-trip fidelity. Must be delivered via the streaming chunks API — chat.postMessage rejects it as an unsupported block type.
  • Streaming-message chunks APIchat.startStream / chat.appendStream / chat.stopStream now accept a chunks parameter. Added MsgOptionChunks along with a StreamChunk interface and four chunk types: MarkdownTextChunk, TaskUpdateChunk, PlanUpdateChunk, and BlocksChunk (each with a New*Chunk constructor). This is the supported transport for streaming Block Kit content and the new agent-UI blocks in particular (which chat.postMessage rejects as Unsupported block type).
  • MsgOptionTaskDisplayMode — New option for chat.startStream controlling whether task chunks render as a sequential timeline or a grouped plan. Accepts TaskDisplayModeTimeline or TaskDisplayModePlan.
  • Added Username, IconURL, and IconEmoji fields to AssistantThreadsSetStatusParameters, forwarded by SetAssistantThreadsStatusContext, matching the new optional parameters on assistant.threads.setStatus for customising the status-update presentation.
  • Exposed SocketmodeHandler.DispatchEvent (previously the unexported dispatcher), enabling integration tests to exercise registered handlers without a live WebSocket connection. The unexported dispatcher is kept as

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/slack-go/slack&package-manager=go_modules&previous-version=0.13.0&new-version=0.23.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 9dd38b2b53..d5aa959a84 100644 --- a/go.mod +++ b/go.mod @@ -608,7 +608,7 @@ require ( github.com/sirupsen/logrus v1.9.4 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/slack-go/slack v0.13.0 // indirect + github.com/slack-go/slack v0.23.1 // indirect github.com/sonatard/noctx v0.5.1 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect diff --git a/go.sum b/go.sum index 2701faaaa0..fb8f3d2525 100644 --- a/go.sum +++ b/go.sum @@ -697,7 +697,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= @@ -876,7 +875,6 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= @@ -1424,8 +1422,8 @@ github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+W github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= -github.com/slack-go/slack v0.13.0 h1:7my/pR2ubZJ9912p9FtvALYpbt0cQPAqkRy2jaSI1PQ= -github.com/slack-go/slack v0.13.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/slack-go/slack v0.23.1 h1:ZS5B96wxxYQRwvJ3/vJFtqtUZi3tXhsZCyT44Nv7M80= +github.com/slack-go/slack v0.23.1/go.mod h1:H0yR/YBuRJ39RkE+JpV/d/oEsbanzTRowR82bCN0cEs= github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= From 1109370320f768dcdb2010d585814cfbbb40b5e8 Mon Sep 17 00:00:00 2001 From: Mereta Date: Fri, 15 May 2026 10:30:41 +0100 Subject: [PATCH 419/448] fix(clang-injection): Validate Retina dir header (#2328) # Security Fix: Prevent Clang Argument Injection via RETINA_VMLINUX_HEADER_DIR ## Summary Fixes a **High severity** information disclosure vulnerability where the `RETINA_VMLINUX_HEADER_DIR` environment variable could be exploited to inject clang arguments, enabling arbitrary file reads through clang's `--config` flag. This fix implements: 1. **Input Validation**: Block dangerous characters at the source 2. **Safe Default**: Always fall back to known-good value 3. **Security Logging**: Warn when suspicious input is detected 4. **No Breaking Changes**: Default behavior unchanged ## Vulnerability Details **Attack Vector**: Argument injection during eBPF compilation **Impact**: Information disclosure - leak sensitive files (passwords, tokens, keys) **Prerequisites**: Ability to modify Retina agent DaemonSet configuration The `RETINA_VMLINUX_HEADER_DIR` environment variable is read without validation and directly incorporated into clang command-line arguments via the `-I` flag: ```go // Before (vulnerable) runtimeIncludeDir := "-I" + loader.VmlinuxHeaderDir() // If RETINA_VMLINUX_HEADER_DIR="/tmp/fake --config /etc/shadow" // becomes: -I/tmp/fake --config /etc/shadow ``` Clang interprets this as two separate arguments: 1. `-I/tmp/fake` (include directory) 2. `--config /etc/shadow` (read config from file) File contents leak via clang error messages in pod logs. **Example Attack**: ```yaml # Malicious DaemonSet modification env: - name: RETINA_VMLINUX_HEADER_DIR value: "/tmp/fake --config /etc/shadow" ``` **Files at Risk**: - `/etc/shadow` - Password hashes - `/etc/passwd` - User information - `/var/run/secrets/kubernetes.io/serviceaccount/token` - K8s service account token - `/root/.ssh/id_rsa` - SSH private keys - Application secrets, certificates, configuration files ### Validation Rules - Reject spaces (prevents multi-argument injection) - Reject tabs/newlines (prevents hidden arguments) - Reject dashes (prevents flag injection like `--config`) - Fall back to safe default `/tmp/retina/include` - Log warning for security monitoring ## Testing ### Unit Tests Added 9 test cases in `pkg/loader/vmlinux_test.go`: **All tests passing**: `go test -v ./pkg/loader/... -run TestVmlinux` ### Manual Validation ``` # Deploy with malicious env var kubectl set env daemonset/retina-agent -n kube-system \ RETINA_VMLINUX_HEADER_DIR="/tmp/headers --config /etc/shadow" ``` Pre Fix: image Post Fix: image ## Impact Assessment ### No Impact on Existing Behavior - Environment variable is not set in deployments - Default path `/tmp/retina/include` is always used - Variable only configurable via Helm values in standard deployment: ```yaml daemonset: container: retina: env: [] # Empty by default ``` - Hubble deployment has no provision for custom env vars Signed-off-by: mereta --- pkg/loader/vmlinux.go | 23 ++++++++ pkg/loader/vmlinux_test.go | 117 +++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/pkg/loader/vmlinux.go b/pkg/loader/vmlinux.go index 4953a1f2c8..cb0bc0c194 100644 --- a/pkg/loader/vmlinux.go +++ b/pkg/loader/vmlinux.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" "time" + "unicode" "github.com/microsoft/retina/pkg/log" "go.uber.org/zap" @@ -38,6 +39,28 @@ func VmlinuxHeaderDir() string { return DefaultVmlinuxHeaderDir } + // Security: Prevent argument injection via environment variable + // Block any path containing whitespace that could be used to inject + // additional clang arguments (e.g., "--config /etc/passwd") + // Also block paths starting with dash (would be interpreted as a flag) + for _, r := range dir { + if unicode.IsSpace(r) { + log.Logger().Named("vmlinux").Warn( + "RETINA_VMLINUX_HEADER_DIR contains whitespace, using default", + zap.String("rejected_value", dir), + ) + return DefaultVmlinuxHeaderDir + } + } + + if strings.HasPrefix(dir, "-") { + log.Logger().Named("vmlinux").Warn( + "RETINA_VMLINUX_HEADER_DIR starts with dash (potential flag injection), using default", + zap.String("rejected_value", dir), + ) + return DefaultVmlinuxHeaderDir + } + return dir } diff --git a/pkg/loader/vmlinux_test.go b/pkg/loader/vmlinux_test.go index ac505391b0..f939e39f0c 100644 --- a/pkg/loader/vmlinux_test.go +++ b/pkg/loader/vmlinux_test.go @@ -36,3 +36,120 @@ func TestGenerateVmlinuxH(t *testing.T) { require.NoError(t, err) require.Contains(t, string(content), "typedef") } + +func TestVmlinuxHeaderDir_Security(t *testing.T) { + // Initialize logger for test + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + + tests := []struct { + name string + envValue string + expected string + desc string + }{ + { + name: "default when empty", + envValue: "", + expected: DefaultVmlinuxHeaderDir, + desc: "Should use default when env var is empty", + }, + { + name: "valid path", + envValue: "/custom/path/headers", + expected: "/custom/path/headers", + desc: "Should accept valid path without special characters", + }, + { + name: "valid path with dashes", + envValue: "/tmp/fake-config", + expected: "/tmp/fake-config", + desc: "Should accept valid path with dashes in the middle", + }, + { + name: "valid path with multiple dashes", + envValue: "/opt/my-app/retina-headers", + expected: "/opt/my-app/retina-headers", + desc: "Should accept valid path with multiple dashes", + }, + { + name: "block space injection", + envValue: "/tmp/fake --config /etc/passwd", + expected: DefaultVmlinuxHeaderDir, + desc: "Should reject path with spaces (argument injection attempt)", + }, + { + name: "block leading dash (flag injection)", + envValue: "--config=/etc/passwd", + expected: DefaultVmlinuxHeaderDir, + desc: "Should reject path starting with dash (would be interpreted as flag)", + }, + { + name: "block config flag", + envValue: "/tmp/dir --config /etc/shadow", + expected: DefaultVmlinuxHeaderDir, + desc: "Should block clang --config file leak attack", + }, + { + name: "block tab injection", + envValue: "/tmp/fake\t--config\t/etc/shadow", + expected: DefaultVmlinuxHeaderDir, + desc: "Should reject path with tabs", + }, + { + name: "block newline injection", + envValue: "/tmp/fake\n--config /etc/passwd", + expected: DefaultVmlinuxHeaderDir, + desc: "Should reject path with newlines", + }, + { + name: "trimmed whitespace valid", + envValue: " /custom/path ", + expected: "/custom/path", + desc: "Should trim leading/trailing whitespace from valid paths", + }, + { + name: "block multiple arguments", + envValue: "/tmp -I/etc -w /tmp/out.txt", + expected: DefaultVmlinuxHeaderDir, + desc: "Should block attempts to inject multiple clang arguments", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set environment variable + if tt.envValue != "" { + err := os.Setenv(VmlinuxHeaderDirEnv, tt.envValue) + require.NoError(t, err) + defer os.Unsetenv(VmlinuxHeaderDirEnv) + } else { + os.Unsetenv(VmlinuxHeaderDirEnv) + } + + // Call function and verify result + result := VmlinuxHeaderDir() + require.Equal(t, tt.expected, result, tt.desc) + }) + } +} + +func TestVmlinuxHeaderDir_PreventArgumentInjection(t *testing.T) { + // Initialize logger for test + _, err := log.SetupZapLogger(log.GetDefaultLogOpts()) + require.NoError(t, err) + + // Simulate attack: inject --config flag to leak /etc/passwd + maliciousInput := "/tmp/headers --config /etc/passwd" + err = os.Setenv(VmlinuxHeaderDirEnv, maliciousInput) + require.NoError(t, err) + defer os.Unsetenv(VmlinuxHeaderDirEnv) + + // Get the directory (should be sanitized to default) + dir := VmlinuxHeaderDir() + + // Verify attack was blocked + require.Equal(t, DefaultVmlinuxHeaderDir, dir, "Malicious input should be rejected") + require.NotContains(t, dir, "--config", "Result should not contain injected flag") + require.NotContains(t, dir, " ", "Result should not contain spaces") +} From cc11656e189e58c83873779dde1822bfff5723e1 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Fri, 15 May 2026 10:31:26 +0100 Subject: [PATCH 420/448] fix(ci): prevent template injection in e2e and perf workflows (#2356) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Routes `${{ inputs.* }}` values through step-level `env:` and references them as quoted shell variables (`"$VAR"`) in the `Run E2E` and `Run performance measurement for Retina` steps, eliminating GitHub Actions template-injection sinks in the `run:` blocks. ## Motivation `e2e.yaml` and `perf-template.yaml` interpolated workflow inputs directly into shell scripts. Although both workflows are gated to `workflow_call` / `workflow_dispatch` (caller already has repo write), this still: - Violates the pattern already used elsewhere in this repo (see `commit-message.yaml`, which passes `github.event.pull_request.title` via `env: TITLE` and references `"$TITLE"`). ## Changes - `.github/workflows/e2e.yaml` — `Run E2E` step: added `IMAGE_TAG`, `IMAGE_REGISTRY`, `IMAGE_NAMESPACE`, `USE_EXISTING_INFRA`, `INPUT_CLUSTER_NAME`, `INPUT_RESOURCE_GROUP` to `env:`. The `${{ !inputs.use_existing_infra }}` negation is now computed in bash as `CREATE_INFRA` / `DELETE_INFRA`. - `.github/workflows/perf-template.yaml` — `Run performance measurement for Retina` step: added `TAG`, `REGISTRY`, `NAMESPACE`, `MODE` to `env:`; removed the redundant local-variable reassignment block; quoted all expansions in the `go test` invocation. ## Compatibility No interface changes — workflow inputs, secrets, and resulting `go test` command lines are identical to before. No callers need to be updated. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Pipeline runs with change: - https://github.com/microsoft/retina/actions/runs/25907691013 - https://github.com/microsoft/retina/actions/runs/25868604325 ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/workflows/e2e.yaml | 19 +++++++++++++++---- .github/workflows/perf-template.yaml | 11 +++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index e7e6322f3a..5339875dbe 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -141,16 +141,27 @@ jobs: AZURE_AGENT_LINUX_SKU: ${{ inputs.azure_agent_linux_sku }} AZURE_AGENT_WINDOWS_SKU: ${{ inputs.azure_agent_windows_sku }} AZURE_AGENT_LINUX_ARM_SKU: ${{ inputs.azure_agent_linux_arm_sku }} + IMAGE_TAG: ${{ inputs.image_tag }} + IMAGE_REGISTRY: ${{ inputs.image_registry }} + IMAGE_NAMESPACE: ${{ inputs.image_namespace }} + USE_EXISTING_INFRA: ${{ inputs.use_existing_infra }} + INPUT_CLUSTER_NAME: ${{ inputs.cluster_name }} + INPUT_RESOURCE_GROUP: ${{ inputs.resource_group }} shell: bash run: | set -euo pipefail - if [ "${{ inputs.use_existing_infra }}" = "true" ]; then - export CLUSTER_NAME=${{ inputs.cluster_name }} - export AZURE_RESOURCE_GROUP=${{ inputs.resource_group }} + if [ "$USE_EXISTING_INFRA" = "true" ]; then + export CLUSTER_NAME="$INPUT_CLUSTER_NAME" + export AZURE_RESOURCE_GROUP="$INPUT_RESOURCE_GROUP" + CREATE_INFRA=false + DELETE_INFRA=false + else + CREATE_INFRA=true + DELETE_INFRA=true fi - go test -v ./test/e2e/. -timeout 60m -tags=e2e -count=1 -args -image-tag=${{ inputs.image_tag }} -image-registry=${{ inputs.image_registry }} -image-namespace=${{ inputs.image_namespace }} -create-infra=${{ !inputs.use_existing_infra }} -delete-infra=${{ !inputs.use_existing_infra }} + go test -v ./test/e2e/. -timeout 60m -tags=e2e -count=1 -args -image-tag="$IMAGE_TAG" -image-registry="$IMAGE_REGISTRY" -image-namespace="$IMAGE_NAMESPACE" -create-infra="$CREATE_INFRA" -delete-infra="$DELETE_INFRA" - name: Cleanup resource group if: always() diff --git a/.github/workflows/perf-template.yaml b/.github/workflows/perf-template.yaml index 3f391302a0..f952c83b76 100644 --- a/.github/workflows/perf-template.yaml +++ b/.github/workflows/perf-template.yaml @@ -89,17 +89,16 @@ jobs: AZURE_AGENT_LINUX_SKU: ${{ inputs.azure-agent-linux-sku }} AZURE_AGENT_WINDOWS_SKU: ${{ inputs.azure-agent-windows-sku }} AZURE_AGENT_LINUX_ARM_SKU: ${{ inputs.azure-agent-linux-arm-sku }} + TAG: ${{ inputs.tag }} + REGISTRY: ${{ inputs.image-registry }} + NAMESPACE: ${{ inputs.image-namespace }} + MODE: ${{ inputs.retina-mode }} shell: bash run: | set -euo pipefail - TAG="${{ inputs.tag }}" - REGISTRY="${{ inputs.image-registry }}" - NAMESPACE="${{ inputs.image-namespace }}" - MODE="${{ inputs.retina-mode }}" - echo "Running in $MODE mode..." - go test -v ./test/e2e/. -timeout 2h -tags=perf -count=1 -args -image-tag=$TAG -image-registry=$REGISTRY -image-namespace=$NAMESPACE -retina-mode=$MODE + go test -v ./test/e2e/. -timeout 2h -tags=perf -count=1 -args -image-tag="$TAG" -image-registry="$REGISTRY" -image-namespace="$NAMESPACE" -retina-mode="$MODE" - name: Cleanup resource group if: always() From 6e3dc601fb4e670b260cf2a8195a25dd5e7129b5 Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Fri, 15 May 2026 16:17:34 +0100 Subject: [PATCH 421/448] fix(ci): fix scale test node sku (#2363) # Description There was an extra 'd' in the sku name. Standard_D4ds_v3 -> Standard_D4s_v3 ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- test/e2e/framework/azure/skus.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/framework/azure/skus.go b/test/e2e/framework/azure/skus.go index c8ab35a260..1ba63b6d25 100644 --- a/test/e2e/framework/azure/skus.go +++ b/test/e2e/framework/azure/skus.go @@ -3,7 +3,7 @@ package azure import "os" var ( - AgentLinuxSKU = skuFromEnv("AZURE_AGENT_LINUX_SKU", "Standard_D4ds_v3") + AgentLinuxSKU = skuFromEnv("AZURE_AGENT_LINUX_SKU", "Standard_D4s_v3") AgentLinuxARMSKU = skuFromEnv("AZURE_AGENT_LINUX_ARM_SKU", "Standard_D4pds_v5") AgentWindowsSKU = skuFromEnv("AZURE_AGENT_WINDOWS_SKU", "Standard_D4ds_v4") ) From 1c29d9c70d9cbff76b984a2aa4c6ee230ae79743 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Mon, 18 May 2026 09:29:52 +0100 Subject: [PATCH 422/448] fix(cve-operator): Remove unused EnablePProf function exposing pprof on all interfaces (#2364) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Summary Remove the dead EnablePProf() function from the operator's standard deployment code. This function bound Go's pprof debug endpoints to :8082 (all network interfaces), which was flagged as a medium-severity vulnerability (OWASP A05 — Security Misconfiguration). ## Changes Removed EnablePProf() from deployment.go as this function was never called Removed now-unused `net/http` and `net/http/pprof` imports ## Screenshots (if applicable) or Testing Completed - go build retina. passes - go test retina. passes --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- operator/cmd/standard/deployment.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/operator/cmd/standard/deployment.go b/operator/cmd/standard/deployment.go index 41a7469d57..0c170371df 100644 --- a/operator/cmd/standard/deployment.go +++ b/operator/cmd/standard/deployment.go @@ -6,8 +6,6 @@ package standard import ( "context" "fmt" - "net/http" - "net/http/pprof" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. @@ -243,20 +241,6 @@ func (o *Operator) Start() error { return nil } -func EnablePProf() { - pprofmux := http.NewServeMux() - pprofmux.HandleFunc("/debug/pprof/", pprof.Index) - pprofmux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) - pprofmux.HandleFunc("/debug/pprof/profile", pprof.Profile) - pprofmux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) - pprofmux.HandleFunc("/debug/pprof/trace", pprof.Trace) - pprofmux.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine")) - - if err := http.ListenAndServe(":8082", pprofmux); err != nil { //nolint:gosec // TODO replace with secure server that supports timeout - panic(err) - } -} - func initLogging(cfg *config.OperatorConfig, applicationInsightsID string) (*log.ZapLogger, error) { logOpts := &log.LogOpts{ Level: cfg.LogLevel, From 261f9c2df83a8dfd3a59ce9ac65b9395c021e9a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 12:26:49 -0400 Subject: [PATCH 423/448] deps: Bump the actions-patch group with 2 updates (#2365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the actions-patch group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [opentofu/setup-opentofu](https://github.com/opentofu/setup-opentofu). Updates `github/codeql-action` from 4.35.4 to 4.35.5
Release notes

Sourced from github/codeql-action's releases.

v4.35.5

  • We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. #3899
  • For performance and accuracy reasons, improved incremental analysis will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. #3791
  • If multiple inputs are provided for the GitHub-internal analysis-kinds input, only code-scanning will be enabled. The analysis-kinds input is experimental, for GitHub-internal use only, and may change without notice at any time. #3892
  • Added an experimental change which, when running a Code Scanning analysis for a PR with improved incremental analysis enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. #3880
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

  • Breaking change: Bump the minimum required CodeQL bundle version to 2.19.4. #3894
  • Add support for SHA-256 Git object IDs. #3893

4.35.5 - 15 May 2026

  • We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. #3899
  • For performance and accuracy reasons, improved incremental analysis will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. #3791
  • If multiple inputs are provided for the GitHub-internal analysis-kinds input, only code-scanning will be enabled. The analysis-kinds input is experimental, for GitHub-internal use only, and may change without notice at any time. #3892
  • Added an experimental change which, when running a Code Scanning analysis for a PR with improved incremental analysis enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. #3880

4.35.4 - 07 May 2026

  • Update default CodeQL bundle version to 2.25.4. #3881

4.35.3 - 01 May 2026

  • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. #3837
  • Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. #3850
  • Best-effort connection tests for private registries now use GET requests instead of HEAD for better compatibility with various registry implementations. For NuGet feeds, the test is now always performed against the service index. #3853
  • Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. #3852
  • Update default CodeQL bundle version to 2.25.3. #3865

4.35.2 - 15 Apr 2026

  • The undocumented TRAP cache cleanup feature that could be enabled using the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the trap-caching: false input to the init Action. #3795
  • The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. #3789
  • Python analysis on GHES no longer extracts the standard library, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. #3794
  • Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. #3807
  • Update default CodeQL bundle version to 2.25.2. #3823

4.35.1 - 27 Mar 2026

4.35.0 - 27 Mar 2026

4.34.1 - 20 Mar 2026

  • Downgrade default CodeQL bundle version to 2.24.3 due to issues with a small percentage of Actions and JavaScript analyses. #3762

4.34.0 - 20 Mar 2026

... (truncated)

Commits
  • 9e0d7b8 Merge pull request #3905 from github/update-v4.35.5-d4b485515
  • 6d7d599 Add changelog entry for #3899
  • 51f7e38 Update changelog for v4.35.5
  • d4b4855 Merge pull request #3899 from github/mbg/esbuild/split
  • 127de81 Merge remote-tracking branch 'origin/main' into mbg/esbuild/split
  • 7fde13f Use src + basename in header to avoid issues on Windows
  • dfa61e7 Improve pattern matching and error handling
  • 52aafec Import and call runWrapper normally in analyze tests
  • 0d08c01 Auto-generate shared bundle
  • 14085a6 Auto-generate entry points
  • Additional commits viewable in compare view

Updates `opentofu/setup-opentofu` from 2.0.0 to 2.0.1
Release notes

Sourced from opentofu/setup-opentofu's releases.

v2.0.1

What's Changed

New Contributors

Full Changelog: https://github.com/opentofu/setup-opentofu/compare/v2...v2.0.1

Commits
  • 847eaa4 chore(deps): Bump @​actions/http-client from 4.0.0 to 4.0.1 (#114)
  • 34bf4e3 feat(acc): Add provider_acceptance_tests input for automated acceptance test ...
  • 4bcfe8c feat: added support for providing optional checksums for ZIP validation (#107)
  • 03a9076 deps: picomatch in npm audit (#103)
  • ba1f8b8 chore(ci): dependabot actions ecosystem, conventional commits (#98)
  • 26ccb9b Update README with latest action versions. (#99)
  • b572e07 feat(error-handling): error notification for network failures (#94)
  • 4959f8f fix: npm audit
  • See full diff in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/test-multicloud.yml | 2 +- .github/workflows/trivy.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 6b21642156..efe333ec31 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml index 1fb2150f93..3719d1bc8b 100644 --- a/.github/workflows/test-multicloud.yml +++ b/.github/workflows/test-multicloud.yml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 30 steps: - - uses: opentofu/setup-opentofu@fc711fa910b93cba0f3fbecaafc9f42fd0c411cb # v2.0.0 + - uses: opentofu/setup-opentofu@847eaa4afeb791b06daa46e8eafa8b1b68d7cfb4 # v2.0.1 with: tofu_version: 1.8.3 diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index 2b80e84682..c4403df694 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: sarif_file: "trivy-results.sarif" From 1f9ebdbeba756defa6407a46659bf696df7c56fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 17:44:15 -0400 Subject: [PATCH 424/448] deps: Bump github.com/go-git/go-git/v5 from 5.19.0 to 5.19.1 (#2366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.19.0 to 5.19.1.
Release notes

Sourced from github.com/go-git/go-git/v5's releases.

v5.19.1

What's Changed

Full Changelog: https://github.com/go-git/go-git/compare/v5.19.0...v5.19.1

Commits
  • 3c3be60 Merge pull request #2137 from go-git/validate-v5
  • 3fba897 plumbing: format/packfile, cap delta chain depth in parser
  • a97d660 Merge pull request #2125 from hiddeco/v5/format-input-bounds
  • aeaa125 plumbing: format/objfile, require Header before Read
  • 1f38e17 plumbing: format/packfile, bound inflate size
  • f7545a0 plumbing: format/idxfile, bound nr by file size
  • 170b881 Merge pull request #2116 from pjbgf/symlink-v5
  • 7b6d994 Merge pull request #2117 from hiddeco/v5/worktree-fs-mkdirall-root-noop
  • f0709b3 git: Stop validating symlink target paths
  • 776d00f git: Allow MkdirAll on worktree-root paths
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-git/go-git/v5&package-manager=go_modules&previous-version=5.19.0&new-version=5.19.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d5aa959a84..1bf0ccc04f 100644 --- a/go.mod +++ b/go.mod @@ -431,7 +431,7 @@ require ( github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.9.0 // indirect - github.com/go-git/go-git/v5 v5.19.0 // indirect + github.com/go-git/go-git/v5 v5.19.1 // indirect github.com/go-openapi/swag/cmdutils v0.25.5 // indirect github.com/go-openapi/swag/conv v0.25.5 // indirect github.com/go-openapi/swag/fileutils v0.25.5 // indirect diff --git a/go.sum b/go.sum index fb8f3d2525..dfa29a9092 100644 --- a/go.sum +++ b/go.sum @@ -622,8 +622,8 @@ github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmm github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.19.0 h1:+WkVUQZSy/F1Gb13udrMKjIM2PrzsNfDKFSfo5tkMtc= -github.com/go-git/go-git/v5 v5.19.0/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= +github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= +github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= From 40335ce83f357ef5ed49bc9fa165d69fb89f5ec5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 21:30:30 -0400 Subject: [PATCH 425/448] deps: Bump google.golang.org/grpc from 1.81.0 to 1.81.1 (#2368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.81.0 to 1.81.1.
Release notes

Sourced from google.golang.org/grpc's releases.

Release 1.81.1

Security

  • xds/rbac: Fix a potential authorization bypass caused by incorrectly falling through URI/DNS SANs to Subject Distinguished Name (DN) when matching the authenticated principal name. With this fix, only the first non-empty identity source will be used, as per gRFC A41. (#9111)

Bug Fixes

  • otel: Segregate client and server RPC information used for metrics and traces, to avoid one overwriting the other. (#9081)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.81.0&new-version=1.81.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1bf0ccc04f..e4139242f0 100644 --- a/go.mod +++ b/go.mod @@ -257,7 +257,7 @@ require ( go.uber.org/mock v0.6.0 go.uber.org/zap/exp v0.3.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f - google.golang.org/grpc v1.81.0 + google.golang.org/grpc v1.81.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gotest.tools v2.2.0+incompatible gotest.tools/v3 v3.5.2 diff --git a/go.sum b/go.sum index dfa29a9092..e4c0ae6a5d 100644 --- a/go.sum +++ b/go.sum @@ -1929,8 +1929,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= -google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From a481e45ff71aad1c840248a8dcd5d2815d35c1a4 Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Thu, 21 May 2026 13:02:32 +0100 Subject: [PATCH 426/448] fix(capture): make HostPath a subpath under a fixed base dir (#2335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem `Capture.spec.outputConfiguration.hostPath` was passed unchecked into `corev1.HostPathVolumeSource.Path`. Any user able to create a `Capture` CR could mount an arbitrary host directory RW into a privileged pod and write artifacts anywhere on the node. ## Fix `HostPath` is now a **relative subpath name**. The operator mounts `${baseDir}/${hostPath}`, where `baseDir` is set by the cluster operator via Helm value `capture.hostPathBaseDir` (default `/var/log/retina/captures`). CR authors cannot influence `baseDir`. Validation rejects (loudly, no silent rewrite): - empty / `.` - absolute paths (POSIX `/`, Windows `C:\`, leading `\`) - any `..` segment, before or after `filepath.Clean` - defense-in-depth: cleaned join must stay under `baseDir` The resolved path is used for `HostPathVolumeSource.Path`, the container `VolumeMount.MountPath`, and the `CAPTURE_OUTPUT_LOCATION_HOST_PATH` env var. ## Key changes - New `pkg/capture/hostpath_validation.go` + tests (`validateHostPath`, sentinel errors, `DefaultHostPathBaseDir`). - `pkg/capture/crd_to_job.go`: `validateCapture` rejects early; `initJobTemplate` and `obtainCaptureOutputEnv` use the resolved path. - `pkg/config/capture.go` + `operator/config/config.go`: new `CaptureHostPathBaseDir` (defaulted, cleaned, must be absolute). - Helm: `capture.hostPathBaseDir` in `values.yaml` and `operator-configmap.yaml`. - CLI: `--host-path` default is now `retina`; new `--host-path-base-dir` flag; auto-allow hack removed. - CRD godoc + manifest regenerated; samples and docs updated. ## Breaking change Capture CRs with an absolute `hostPath` (e.g. `/tmp/retina`) are rejected. Migration: use a bare name (`retina`); the mount becomes `/var/log/retina/captures/retina`. Operators needing a different root set `capture.hostPathBaseDir`. ## Test - `go test ./pkg/capture/ ./pkg/config/ ./operator/config/ ./cli/...` — pass - `go vet ./pkg/capture/ ./pkg/config/ ./operator/config/ ./cli/...` — clean - Unit cases: empty, `.`, POSIX/Windows absolute, pre-clean `..`, post-clean `foo/../bar`, escape, accepted nested subpaths. - Manual kind run: absolute / `..` / `foo/../bar` rejected with no Job created and a single `CaptureError` condition; bare subpath mounts at `${baseDir}/${name}`; overriding `capture.hostPathBaseDir` relocates the mount without changing the CR. ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ### Negative — absolute HostPath is rejected loudly Screenshot 2026-05-18 164606 ### Negative — parent segment is rejected Screenshot 2026-05-18 164729 ### Negative — post-clean traversal is rejected Screenshot 2026-05-18 164804 ### Positive — bare subpath is accepted Screenshot 2026-05-18 165003 ### Override the base directory Screenshot 2026-05-18 165500 ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- cli/cmd/capture/capture.go | 1 + cli/cmd/capture/create.go | 20 ++- cli/cmd/capture/create_test.go | 96 ++++++++++---- cli/cmd/capture/download_test.go | 31 +++++ crd/api/v1alpha1/capture_types.go | 12 +- .../retina/templates/operator-configmap.yaml | 3 + .../controller/helm/retina/values.yaml | 6 + docs/02-Installation/03-Config.md | 1 + docs/04-Captures/03-crd.md | 8 +- .../04-Captures/04-managed-storage-account.md | 2 +- docs/05-Concepts/CRDs/Capture.md | 4 +- operator/config/config.go | 20 ++- pkg/capture/crd_to_job.go | 68 ++++++++-- pkg/capture/crd_to_job_test.go | 118 +++++++++++++---- pkg/capture/hostpath_validation.go | 109 ++++++++++++++++ pkg/capture/hostpath_validation_test.go | 94 ++++++++++++++ pkg/capture/utils/annotations.go | 11 +- pkg/capture/utils/annotations_test.go | 121 ++++++++++++++++++ pkg/config/capture.go | 8 ++ .../operator/capture/controller.go | 1 - .../capture-specific-pod-on-a-node.yaml | 2 +- samples/capture/node-s3upload-aws.yaml | 2 +- samples/capture/node-s3upload-minio.yaml | 2 +- samples/capture/nodeblobupload.yaml | 2 +- samples/capture/podblobupload.yaml | 2 +- 25 files changed, 657 insertions(+), 87 deletions(-) create mode 100644 pkg/capture/hostpath_validation.go create mode 100644 pkg/capture/hostpath_validation_test.go create mode 100644 pkg/capture/utils/annotations_test.go diff --git a/cli/cmd/capture/capture.go b/cli/cmd/capture/capture.go index 70cafa7e55..a1457c2c73 100644 --- a/cli/cmd/capture/capture.go +++ b/cli/cmd/capture/capture.go @@ -19,6 +19,7 @@ type Opts struct { duration time.Duration excludeFilter string hostPath string + hostPathBaseDir string includeFilter string includeMetadata bool interfaces string diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index a18efcfbfe..e9e512c460 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -34,9 +34,15 @@ import ( ) const ( - DefaultDebug bool = false - DefaultDuration time.Duration = 1 * time.Minute - DefaultHostPath string = "/mnt/retina/captures" + DefaultDebug bool = false + DefaultDuration time.Duration = 1 * time.Minute + // DefaultHostPath is the default subpath (joined under DefaultHostPathBaseDir on + // the node) where capture artifacts are stored. It is a bare name, not an + // absolute path: absolute paths are rejected by the operator. + DefaultHostPath string = "retina" + // DefaultHostPathBaseDir is the default node-side parent directory for capture + // artifacts; the user-supplied --host-path subpath is joined under it. + DefaultHostPathBaseDir string = "/var/log/retina/captures" DefaultIncludeMetadata bool = true DefaultJobNumLimit int = 0 DefaultMaxSize int = 100 @@ -50,7 +56,8 @@ const ( var createExample = templates.Examples(i18n.T(` # Select nodes by node name and copy the artifacts to the node host path - kubectl retina capture create --host-path /mnt/retina/testcapture --node-names "," + # (joined under the operator-configured base directory; default /var/log/retina/captures/testcapture) + kubectl retina capture create --host-path testcapture --node-names "," # Select pods determined by pod-selectors and namespace-selectors kubectl retina capture create --namespace capture --pod-selectors="k8s-app=kube-dns" --namespace-selectors="kubernetes.io/metadata.name=kube-system" @@ -205,7 +212,9 @@ func NewCreateSubCommand(kubeClient kubernetes.Interface) *cobra.Command { "A comma-separated list of pod labels to select pods on which the network capture will be performed") createCapture.Flags().StringVar(&opts.namespaceSelectors, "namespace-selectors", "", "A comma-separated list of namespace labels to filter which namespaces will be targeted for packet capture (used with --pod-selectors)") - createCapture.Flags().StringVar(&opts.hostPath, "host-path", DefaultHostPath, "HostPath of the node to store the capture files") + createCapture.Flags().StringVar(&opts.hostPath, "host-path", DefaultHostPath, + "Subpath name (joined under --host-path-base-dir) for capture artifacts on the node. Must be a relative subpath and must not contain '..'.") + createCapture.Flags().StringVar(&opts.hostPathBaseDir, "host-path-base-dir", DefaultHostPathBaseDir, "Absolute base directory on the node under which --host-path is joined") createCapture.Flags().StringVar(&opts.pvc, "pvc", "", "PersistentVolumeClaim under the specified or default namespace to store capture files") createCapture.Flags().StringVar(&opts.blobUpload, "blob-upload", "", "Blob SAS URL with write permission to upload capture files") createCapture.Flags().StringVar(&opts.s3Region, "s3-region", "", "Region where the S3 compatible bucket is located") @@ -443,6 +452,7 @@ func getCLICaptureConfig() config.CaptureConfig { CaptureDebug: opts.debug, CaptureImageVersionSource: captureUtils.VersionSourceCLIVersion, CaptureJobNumLimit: opts.jobNumLimit, + CaptureHostPathBaseDir: opts.hostPathBaseDir, } } diff --git a/cli/cmd/capture/create_test.go b/cli/cmd/capture/create_test.go index 74a7e10810..add7118a25 100644 --- a/cli/cmd/capture/create_test.go +++ b/cli/cmd/capture/create_test.go @@ -12,6 +12,8 @@ import ( "testing" retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" + "github.com/microsoft/retina/internal/buildinfo" + captureUtils "github.com/microsoft/retina/pkg/capture/utils" "github.com/microsoft/retina/pkg/label" "github.com/stretchr/testify/require" batchv1 "k8s.io/api/batch/v1" @@ -340,28 +342,33 @@ func JobsCreatedCorrectly(t *testing.T, kubeClient *fake.Clientset, tc testcase) // Pod Names Tests - Tests for CLI pod name selection functionality -func TestCreateCaptureCommand_PodNamesWithNodeSelector_ShouldFail(t *testing.T) { - // Test that when pod-names is specified with node-selectors, the node selector is overridden - // and the command attempts to use pod names. Since the pod doesn't exist, this will fail. - // This verifies that pod names take precedence over default node selectors. - cmd := NewCommand(fake.NewClientset()) - - cmd.SetArgs([]string{ - "create", - "--name=test-capture", - "--namespace=default", - "--pod-names=nonexistent-pod", - "--node-selectors=kubernetes.io/os=linux", - "--duration=10s", - "--host-path=/tmp/capture", +func TestCreateCaptureCommand_PodNamesClearsDefaultNodeSelector(t *testing.T) { + // When --pod-names is set together with the default --node-selectors, + // the default selector must be cleared so pod names take precedence. + savedNodeSelectors := opts.nodeSelectors + savedPodNames := opts.podNames + savedNamespace := opts.Namespace + savedName := opts.Name + t.Cleanup(func() { + opts.nodeSelectors = savedNodeSelectors + opts.podNames = savedPodNames + opts.Namespace = savedNamespace + opts.Name = savedName }) - buf := new(bytes.Buffer) - cmd.SetOut(buf) + name := "test-capture" + namespace := "default" - err := cmd.Execute() - require.Error(t, err, "command should fail when pod-names specifies a nonexistent pod") - require.Contains(t, err.Error(), "not found", "error should indicate the pod was not found") + opts.nodeSelectors = DefaultNodeSelectors + opts.podNames = "nonexistent-pod" + opts.Namespace = &namespace + opts.Name = &name + + capture, err := createCaptureF(context.Background(), fake.NewClientset()) + require.NoError(t, err) + + require.Equal(t, []string{"nonexistent-pod"}, capture.Spec.CaptureConfiguration.CaptureTarget.PodNames) + require.Nil(t, capture.Spec.CaptureConfiguration.CaptureTarget.NodeSelector) } func TestCreateCaptureWithPodNames_CRDStructure(t *testing.T) { @@ -546,7 +553,7 @@ func TestNodeNamesClearsDefaultNodeSelector(t *testing.T) { "--namespace=default", "--node-names=win-node-1", "--duration=10s", - "--host-path=/tmp/capture", + "--host-path=capture", }, wantNodes: []string{"win-node-1"}, wantErr: false, @@ -559,7 +566,7 @@ func TestNodeNamesClearsDefaultNodeSelector(t *testing.T) { "--namespace=default", "--node-names=lin-node-1", "--duration=10s", - "--host-path=/tmp/capture", + "--host-path=capture", }, wantNodes: []string{"lin-node-1"}, wantErr: false, @@ -572,7 +579,7 @@ func TestNodeNamesClearsDefaultNodeSelector(t *testing.T) { "--namespace=default", "--node-names=lin-node-1,win-node-1", "--duration=10s", - "--host-path=/tmp/capture", + "--host-path=capture", }, wantNodes: []string{"lin-node-1", "win-node-1"}, wantErr: false, @@ -622,3 +629,48 @@ func TestNodeNamesClearsDefaultNodeSelector(t *testing.T) { }) } } + +func TestGetCLICaptureConfig(t *testing.T) { + savedDebug, savedJobNumLimit, savedHostPathBaseDir := opts.debug, opts.jobNumLimit, opts.hostPathBaseDir + t.Cleanup(func() { + opts.debug = savedDebug + opts.jobNumLimit = savedJobNumLimit + opts.hostPathBaseDir = savedHostPathBaseDir + }) + + opts.debug = true + opts.jobNumLimit = 7 + opts.hostPathBaseDir = "/mnt/captures" + + got := getCLICaptureConfig() + + require.Equal(t, buildinfo.Version, got.CaptureImageVersion) + require.Equal(t, captureUtils.VersionSourceCLIVersion, got.CaptureImageVersionSource) + require.True(t, got.CaptureDebug) + require.Equal(t, 7, got.CaptureJobNumLimit) + require.Equal(t, "/mnt/captures", got.CaptureHostPathBaseDir) +} + +func TestCreateCaptureCommand_AbsoluteHostPath_ShouldFail(t *testing.T) { + // --host-path must be a bare subpath; absolute paths are rejected by the + // shared validateHostPath helper used by both the operator and the CLI. + cmd := NewCommand(fake.NewClientset()) + + cmd.SetArgs([]string{ + "create", + "--name=hp-absolute", + "--namespace=default", + "--node-selectors=kubernetes.io/os=linux", + "--duration=10s", + "--host-path=/tmp/foo", + }) + + buf := new(bytes.Buffer) + cmd.SetOut(buf) + cmd.SetErr(buf) + + err := cmd.Execute() + require.Error(t, err, "command should fail when --host-path is absolute") + require.Contains(t, err.Error(), "OutputConfiguration.HostPath", + "error should reference the rejected HostPath field; got: %v", err) +} diff --git a/cli/cmd/capture/download_test.go b/cli/cmd/capture/download_test.go index 25ae298f07..77e3ffcad4 100644 --- a/cli/cmd/capture/download_test.go +++ b/cli/cmd/capture/download_test.go @@ -901,6 +901,8 @@ func TestDownloadCommandFlags(t *testing.T) { // Test all cases with unified approach for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + resetDownloadGlobals(t) + cmd := NewDownloadSubCommand() // Parse flags without executing the command @@ -914,7 +916,36 @@ func TestDownloadCommandFlags(t *testing.T) { } } +// resetDownloadGlobals zeros the package-level globals bound to the download +// command's flags and restores them on test cleanup. Cobra binds flag values +// to these globals, so without resetting between subtests one subtest's flag +// values leak into the next, making tests order-dependent. +func resetDownloadGlobals(t *testing.T) { + t.Helper() + origCaptureName := captureName + origBlobURL := blobURL + origDownloadAll := downloadAll + origDownloadAllNamespaces := downloadAllNamespaces + origOutputPath := outputPath + + captureName = "" + blobURL = "" + downloadAll = false + downloadAllNamespaces = false + outputPath = "" + + t.Cleanup(func() { + captureName = origCaptureName + blobURL = origBlobURL + downloadAll = origDownloadAll + downloadAllNamespaces = origDownloadAllNamespaces + outputPath = origOutputPath + }) +} + func TestDownloadAllCapturesGracefulErrorHandling(t *testing.T) { + resetDownloadGlobals(t) + // Test the graceful error handling by testing individual components // that are used in downloadAllCaptures diff --git a/crd/api/v1alpha1/capture_types.go b/crd/api/v1alpha1/capture_types.go index e5fa45ec09..dfa23cf857 100644 --- a/crd/api/v1alpha1/capture_types.go +++ b/crd/api/v1alpha1/capture_types.go @@ -141,8 +141,16 @@ type CaptureConfigurationFilters struct { // OutputConfiguration indicates the location capture will be stored. type OutputConfiguration struct { - // HostPath stores the capture files into the specified host filesystem. - // If nothing exists at the given path of the host, an empty directory will be created there. + // HostPath is a relative subpath name (e.g. "my-capture") joined under the + // operator-configured host base directory (default /var/log/retina/captures) + // on every node that runs a capture pod. The capture files are written to + // that joined directory, and an empty directory is created there if it does + // not already exist. + // + // HostPath must be a relative subpath: absolute paths (e.g. "/tmp/foo", + // "C:\\foo") and any value containing ".." segments are rejected by the + // operator. CR authors cannot influence the base directory, which is + // controlled by the cluster operator via the operator config. // +optional HostPath *string `json:"hostPath,omitempty"` // PersistentVolumeClaim mounts the supplied PVC into the pod on `/capture` and write the capture files there. diff --git a/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml b/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml index 19d68b0298..ab82bc5ae1 100644 --- a/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml +++ b/deploy/standard/manifests/controller/helm/retina/templates/operator-configmap.yaml @@ -11,6 +11,9 @@ data: remoteContext: {{ .Values.remoteContext }} captureDebug: {{ .Values.capture.debug }} captureJobNumLimit: {{ .Values.capture.jobNumLimit }} +{{- with .Values.capture.hostPathBaseDir }} + captureHostPathBaseDir: {{ . | quote }} +{{- end }} enableManagedStorageAccount: {{ .Values.capture.enableManagedStorageAccount }} telemetryInterval: {{ .Values.operator.telemetryInterval }} {{- if .Values.capture.enableManagedStorageAccount }} diff --git a/deploy/standard/manifests/controller/helm/retina/values.yaml b/deploy/standard/manifests/controller/helm/retina/values.yaml index 76e1c7c758..063fb02ecd 100644 --- a/deploy/standard/manifests/controller/helm/retina/values.yaml +++ b/deploy/standard/manifests/controller/helm/retina/values.yaml @@ -178,6 +178,12 @@ capture: debug: true # jobNumLimit indicates the maximum number of jobs that can be created for each Capture. jobNumLimit: 0 + # hostPathBaseDir is the absolute directory on every node under which Capture + # CRs may write artifacts. The CR field outputConfiguration.hostPath is treated + # as a relative subpath name and joined under this directory; CR authors + # cannot influence the base. Leave empty to use the operator default + # (/var/log/retina/captures). + hostPathBaseDir: "" # enableManagedStorageAccount toggles the use of managed storage account for storing artifacts. # If set to true, the following fields related to Azure credentials must be set. # Ref: docs/captures/managed-storage-account.md diff --git a/docs/02-Installation/03-Config.md b/docs/02-Installation/03-Config.md index 5c9422b206..dc622e1227 100644 --- a/docs/02-Installation/03-Config.md +++ b/docs/02-Installation/03-Config.md @@ -63,4 +63,5 @@ Apply to both Agent and Operator. * `operator.enableRetinaEndpoint`: Allows the operator to monitor and update the cache with Pod metadata. * `capture.captureDebug`: Toggles debug mode for captures. If true, the operator uses the image from the test container registry for the capture workload. Refer to [Capture Image file](../../pkg/capture/utils/capture_image.go) for details on how the debug capture image version is selected. * `capture.captureJobNumLimit`: Sets the maximum number of jobs that can be created for each Capture. +* `capture.hostPathBaseDir`: Absolute directory on every node under which Capture CRs may write artifacts. The CR field `outputConfiguration.hostPath` is treated as a relative subpath name and joined under this directory; CR authors cannot influence the base. Defaults to `/var/log/retina/captures` when unset. * `capture.enableManagedStorageAccount`: Enables the use of a managed storage account for storing artifacts. diff --git a/docs/04-Captures/03-crd.md b/docs/04-Captures/03-crd.md index ca5f17d80a..5b372878a0 100644 --- a/docs/04-Captures/03-crd.md +++ b/docs/04-Captures/03-crd.md @@ -77,7 +77,7 @@ spec: matchLabels: kubernetes.io/os: linux outputConfiguration: - hostPath: /captures + hostPath: example-capture ``` Include / Exclude filters @@ -105,7 +105,7 @@ spec: - 10.224.0.26:80 - 10.224.0.34:8080 outputConfiguration: - hostPath: /captures + hostPath: example-capture ``` Single Pod by Name @@ -125,7 +125,7 @@ spec: podNames: - my-app-pod-abc123 outputConfiguration: - hostPath: /captures + hostPath: example-capture ``` Multiple Pods by Name @@ -146,7 +146,7 @@ spec: - my-app-pod-abc123 - my-app-pod-def456 outputConfiguration: - hostPath: /captures + hostPath: example-capture ``` Additional examples can also be found in the [GitHub capture samples](https://github.com/microsoft/retina/tree/main/samples/capture). diff --git a/docs/04-Captures/04-managed-storage-account.md b/docs/04-Captures/04-managed-storage-account.md index 82cb02b375..cac86be751 100644 --- a/docs/04-Captures/04-managed-storage-account.md +++ b/docs/04-Captures/04-managed-storage-account.md @@ -28,7 +28,7 @@ spec: matchLabels: kubernetes.io/hostname: aks-nodepool1-11396069-vmss000000 outputConfiguration: - hostPath: "/tmp/retina" + hostPath: "retina" blobUpload: blob-sas-url ``` diff --git a/docs/05-Concepts/CRDs/Capture.md b/docs/05-Concepts/CRDs/Capture.md index a7f08d013e..7c6d1af3ee 100644 --- a/docs/05-Concepts/CRDs/Capture.md +++ b/docs/05-Concepts/CRDs/Capture.md @@ -31,7 +31,7 @@ The `Capture` CRD is defined with the following specifications: - **spec.outputConfiguration:** Indicates where the captured data will be stored. It includes the following properties: - `blobUpload`: Specifies a secret containing the blob SAS URL for storing the capture data. - - `hostPath`: Stores the capture files into the specified host filesystem. + - `hostPath`: A relative subpath name (e.g. `my-capture`) joined under the operator-configured host base directory (default `/var/log/retina/captures`) on every node that runs a capture pod. Capture files are written to that joined directory. Absolute paths and `..` segments are rejected. - `persistentVolumeClaim`: Mounts a PersistentVolumeClaim into the Pod to store capture files. - `s3Upload`: Specifies the configuration for uploading capture files to an S3-compatible storage service, including the bucket name, region, and optional custom endpoint. @@ -59,7 +59,7 @@ spec: matchLabels: app: target-app outputConfiguration: - hostPath: /captures + hostPath: example-capture blobUpload: blob-sas-url s3Upload: bucket: retina-bucket diff --git a/operator/config/config.go b/operator/config/config.go index 1c460ac878..e1d444a76f 100644 --- a/operator/config/config.go +++ b/operator/config/config.go @@ -1,10 +1,13 @@ package config import ( + "errors" "fmt" "log" + "path/filepath" "time" + "github.com/microsoft/retina/pkg/capture" "github.com/microsoft/retina/pkg/config" "github.com/spf13/viper" ) @@ -12,8 +15,9 @@ import ( const MinTelemetryInterval time.Duration = 2 * time.Minute var ( - DefaultTelemetryInterval = 5 * time.Minute - ErrorTelemetryIntervalTooSmall = fmt.Errorf("telemetryInterval smaller than %v is not allowed", MinTelemetryInterval) + DefaultTelemetryInterval = 5 * time.Minute + ErrorTelemetryIntervalTooSmall = fmt.Errorf("telemetryInterval smaller than %v is not allowed", MinTelemetryInterval) + ErrCaptureHostPathBaseDirNotAbsolute = errors.New("captureHostPathBaseDir must be an absolute path") ) type OperatorConfig struct { @@ -53,5 +57,17 @@ func GetConfig(cfgFileName string) (*OperatorConfig, error) { return nil, ErrorTelemetryIntervalTooSmall } + // If unset, default the HostPath base directory so that Capture CRs cannot + // place artifacts arbitrarily on the node filesystem. The CR's HostPath is + // always joined under this directory. + if cfg.CaptureHostPathBaseDir == "" { + log.Printf("captureHostPathBaseDir is not set, defaulting to %s", capture.DefaultHostPathBaseDir) + cfg.CaptureHostPathBaseDir = capture.DefaultHostPathBaseDir + } + cfg.CaptureHostPathBaseDir = filepath.Clean(cfg.CaptureHostPathBaseDir) + if !filepath.IsAbs(cfg.CaptureHostPathBaseDir) { + return nil, fmt.Errorf("%w: got %q", ErrCaptureHostPathBaseDirNotAbsolute, cfg.CaptureHostPathBaseDir) + } + return &cfg, nil } diff --git a/pkg/capture/crd_to_job.go b/pkg/capture/crd_to_job.go index ebc00b3f5f..056e2d7155 100644 --- a/pkg/capture/crd_to_job.go +++ b/pkg/capture/crd_to_job.go @@ -117,11 +117,29 @@ func NewCaptureToPodTranslator(kubeClient kubernetes.Interface, logger *log.ZapL return captureToPodTranslator } -func (translator *CaptureToPodTranslator) initJobTemplate(ctx context.Context, capture *retinav1alpha1.Capture) error { +// resolveHostPath validates the user-supplied HostPath subpath against the +// operator-configured base directory and returns the resolved on-node path. +// Returns ("", nil) when no HostPath is configured (HostPath is nil). An +// explicit empty-string HostPath is rejected via validateHostPath so user +// misconfiguration surfaces with a clear error instead of being silently +// ignored. +func (translator *CaptureToPodTranslator) resolveHostPath(oc retinav1alpha1.OutputConfiguration) (string, error) { + if oc.HostPath == nil { + return "", nil + } + resolved, err := validateHostPath(*oc.HostPath, translator.config.CaptureHostPathBaseDir) + if err != nil { + return "", fmt.Errorf("invalid OutputConfiguration.HostPath: %w", err) + } + return resolved, nil +} + +func (translator *CaptureToPodTranslator) initJobTemplate(ctx context.Context, capture *retinav1alpha1.Capture, resolvedHostPath string) error { backoffLimit := int32(0) // NOTE(mainred): We allow the capture pod to run for at most 30 minutes before being deleted to ensure the output is // uploaded, and this happens when the user want to stop a capture on demand by deleting the capture. captureTerminationGracePeriodSeconds := int64(1800) + translator.jobTemplate = &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ GenerateName: fmt.Sprintf("%s-", capture.Name), @@ -134,7 +152,7 @@ func (translator *CaptureToPodTranslator) initJobTemplate(ctx context.Context, c ObjectMeta: metav1.ObjectMeta{ Labels: captureUtils.GetContainerLabelsFromCaptureName(capture.Name), Namespace: capture.Namespace, - Annotations: captureUtils.GetPodAnnotationsFromCapture(capture), + Annotations: captureUtils.GetPodAnnotationsFromCapture(capture, resolvedHostPath), }, Spec: corev1.PodSpec{ HostNetwork: true, @@ -207,16 +225,15 @@ func (translator *CaptureToPodTranslator) initJobTemplate(ctx context.Context, c }, } - if capture.Spec.OutputConfiguration.HostPath != nil && *capture.Spec.OutputConfiguration.HostPath != "" { - translator.l.Info("HostPath is not empty", zap.String("HostPath", *capture.Spec.OutputConfiguration.HostPath)) + if resolvedHostPath != "" { + translator.l.Info("HostPath is not empty", zap.String("HostPath", *capture.Spec.OutputConfiguration.HostPath), zap.String("ResolvedHostPath", resolvedHostPath)) captureFolderHostPathType := corev1.HostPathDirectoryOrCreate - hostPath := *capture.Spec.OutputConfiguration.HostPath hostPathVolume := corev1.Volume{ Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -225,7 +242,7 @@ func (translator *CaptureToPodTranslator) initJobTemplate(ctx context.Context, c hostPathVolumeMount := corev1.VolumeMount{ Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, } translator.jobTemplate.Spec.Template.Spec.Containers[0].VolumeMounts = append(translator.jobTemplate.Spec.Template.Spec.Containers[0].VolumeMounts, hostPathVolumeMount) } @@ -363,7 +380,15 @@ func (translator *CaptureToPodTranslator) TranslateCaptureToJobs(ctx context.Con return nil, err } - if err := translator.initJobTemplate(ctx, capture); err != nil { + // Resolve the HostPath once and reuse it for both the job template (pod + // annotation + volume mount) and the capture workload env. + resolvedHostPath, hpErr := translator.resolveHostPath(capture.Spec.OutputConfiguration) + if hpErr != nil { + translator.l.Error("Rejected HostPath in Capture", zap.Error(hpErr), zap.String("HostPath", *capture.Spec.OutputConfiguration.HostPath)) + return nil, hpErr + } + + if err := translator.initJobTemplate(ctx, capture, resolvedHostPath); err != nil { return nil, err } captureTargetOnNode, err := translator.CalculateCaptureTargetsOnNode(ctx, capture.Spec.CaptureConfiguration.CaptureTarget, capture.Namespace) @@ -371,7 +396,7 @@ func (translator *CaptureToPodTranslator) TranslateCaptureToJobs(ctx context.Con return nil, err } - jobPodEnv, err := translator.ObtainCaptureJobPodEnv(*capture) + jobPodEnv, err := translator.obtainCaptureJobPodEnv(*capture, resolvedHostPath) if err != nil { return nil, err } @@ -579,6 +604,10 @@ func (translator *CaptureToPodTranslator) validateCapture(capture *retinav1alpha capture.Spec.OutputConfiguration.S3Upload == nil { return fmt.Errorf("At least one output configuration should be set") } + + if _, err := translator.resolveHostPath(capture.Spec.OutputConfiguration); err != nil { + return err + } return nil } @@ -944,10 +973,15 @@ func (translator *CaptureToPodTranslator) obtainTcpdumpFilters(captureConfig ret return tcpdumpFilter, nil } -func (translator *CaptureToPodTranslator) obtainCaptureOutputEnv(outputConfiguration retinav1alpha1.OutputConfiguration) (map[captureConstants.CaptureOutputLocationEnvKey]string, error) { +func (translator *CaptureToPodTranslator) obtainCaptureOutputEnv( + outputConfiguration retinav1alpha1.OutputConfiguration, + resolvedHostPath string, +) (map[captureConstants.CaptureOutputLocationEnvKey]string, error) { outputEnv := map[captureConstants.CaptureOutputLocationEnvKey]string{} - if outputConfiguration.HostPath != nil { - outputEnv[captureConstants.CaptureOutputLocationEnvKeyHostPath] = *outputConfiguration.HostPath + if resolvedHostPath != "" { + // Emit the resolved (joined, cleaned) path so the workload writes where + // the HostPath volume is actually mounted in the capture pod. + outputEnv[captureConstants.CaptureOutputLocationEnvKeyHostPath] = resolvedHostPath } if outputConfiguration.PersistentVolumeClaim != nil { outputEnv[captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim] = *outputConfiguration.PersistentVolumeClaim @@ -983,9 +1017,17 @@ func (translator *CaptureToPodTranslator) obtainCaptureOptionEnv(option retinav1 // ObtainCaptureJobPodEnv translates Capture object to Environment variables to capture job Pod. func (translator *CaptureToPodTranslator) ObtainCaptureJobPodEnv(capture retinav1alpha1.Capture) (map[string]string, error) { + resolvedHostPath, err := translator.resolveHostPath(capture.Spec.OutputConfiguration) + if err != nil { + return nil, err + } + return translator.obtainCaptureJobPodEnv(capture, resolvedHostPath) +} + +func (translator *CaptureToPodTranslator) obtainCaptureJobPodEnv(capture retinav1alpha1.Capture, resolvedHostPath string) (map[string]string, error) { jobPodEnv := map[string]string{} - captureOutputEnv, err := translator.obtainCaptureOutputEnv(capture.Spec.OutputConfiguration) + captureOutputEnv, err := translator.obtainCaptureOutputEnv(capture.Spec.OutputConfiguration, resolvedHostPath) if err != nil { return nil, err } diff --git a/pkg/capture/crd_to_job_test.go b/pkg/capture/crd_to_job_test.go index 76604f6f66..c9349df8ad 100644 --- a/pkg/capture/crd_to_job_test.go +++ b/pkg/capture/crd_to_job_test.go @@ -45,6 +45,7 @@ func NewCaptureToPodTranslatorForTest(kubeClient kubernetes.Interface) *CaptureT CaptureImageVersion: "v0.0.1-pre", CaptureImageVersionSource: captureUtils.VersionSourceOperatorImageVersion, CaptureJobNumLimit: 10, + CaptureHostPathBaseDir: "/tmp", } captureToPodTranslator := NewCaptureToPodTranslator(kubeClient, log.Logger().Named("test"), config) @@ -491,12 +492,23 @@ func Test_CaptureToPodTranslator_ObtainCaptureJobPodEnv(t *testing.T) { capture: retinav1alpha1.Capture{}, wantErr: true, }, + { + name: "explicit empty hostpath is rejected", + capture: retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + HostPath: pointerUtil.String(""), + }, + }, + }, + wantErr: true, + }, { name: "use hostpath", capture: retinav1alpha1.Capture{ Spec: retinav1alpha1.CaptureSpec{ OutputConfiguration: retinav1alpha1.OutputConfiguration{ - HostPath: pointerUtil.String("/tmp/capture"), + HostPath: pointerUtil.String("capture"), }, }, }, @@ -683,7 +695,7 @@ func Test_CaptureToPodTranslator_RenderJob_NodeSelected(t *testing.T) { startTime := time.Now() - hostPath := "/tmp/capture" // nolint:goconst // Test case needs a var + hostPath := "capture" // nolint:goconst // Test case needs a var err := captureToPodTranslator.initJobTemplate(ctx, &retinav1alpha1.Capture{ Spec: retinav1alpha1.CaptureSpec{ @@ -695,7 +707,7 @@ func Test_CaptureToPodTranslator_RenderJob_NodeSelected(t *testing.T) { Status: retinav1alpha1.CaptureStatus{ StartTime: &metav1.Time{Time: startTime}, }, - }) + }, "/tmp/"+hostPath) if err != nil { t.Errorf("initJobTemplate() want no error, got error %s", err) } @@ -726,7 +738,7 @@ func Test_CaptureToPodTranslator_RenderJob_NodeSelected(t *testing.T) { func Test_CaptureToPodTranslator_ValidateCapture(t *testing.T) { captureName := "capture-test" - hostPath := "/tmp/capture" + hostPath := "capture" nodeName := "node-name" cases := []struct { name string @@ -825,6 +837,55 @@ func Test_CaptureToPodTranslator_ValidateCapture(t *testing.T) { }, } + // Additional negative cases for HostPath validation; share the rest of the spec. + captureSpecWithHostPath := func(hp string) retinav1alpha1.Capture { + return retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{Name: captureName}, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"nodename": nodeName}, + }, + }, + CaptureOption: retinav1alpha1.CaptureOption{ + Duration: &metav1.Duration{Duration: 10 * time.Second}, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{HostPath: &hp}, + }, + } + } + cases = append(cases, + struct { + name string + capture retinav1alpha1.Capture + wantErr bool + }{ + name: "raise error when HostPath is absolute", + capture: captureSpecWithHostPath("/tmp/retina"), + wantErr: true, + }, + struct { + name string + capture retinav1alpha1.Capture + wantErr bool + }{ + name: "raise error when HostPath contains traversal", + capture: captureSpecWithHostPath("foo/../bar"), + wantErr: true, + }, + struct { + name string + capture retinav1alpha1.Capture + wantErr bool + }{ + name: "raise error when HostPath uses parent segment", + capture: captureSpecWithHostPath("../etc"), + wantErr: true, + }, + ) + for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { k8sClient := fakeclientset.NewSimpleClientset() @@ -849,7 +910,8 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { defer cancel() captureName := "capture-test" - hostPath := "/tmp/capture" + hostPath := "capture" + resolvedHostPath := "/tmp/capture" timestamp := file.Now() pvc := "capture-pvc" backoffLimit := int32(0) @@ -1009,7 +1071,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, }, volumes: []corev1.Volume{ @@ -1017,7 +1079,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1025,7 +1087,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1293,7 +1355,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, { Name: captureConstants.CapturePVCVolumeName, @@ -1305,7 +1367,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1321,7 +1383,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1390,7 +1452,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, }, volumes: []corev1.Volume{ @@ -1398,7 +1460,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1406,7 +1468,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1470,7 +1532,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, }, volumes: []corev1.Volume{ @@ -1478,7 +1540,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1486,7 +1548,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1552,7 +1614,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, }, volumes: []corev1.Volume{ @@ -1560,7 +1622,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1568,7 +1630,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1634,7 +1696,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, }, volumes: []corev1.Volume{ @@ -1642,7 +1704,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1650,7 +1712,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1715,7 +1777,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { volumeMounts: []corev1.VolumeMount{ { Name: captureConstants.CaptureHostPathVolumeName, - MountPath: hostPath, + MountPath: resolvedHostPath, }, }, volumes: []corev1.Volume{ @@ -1723,7 +1785,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { Name: captureConstants.CaptureHostPathVolumeName, VolumeSource: corev1.VolumeSource{ HostPath: &corev1.HostPathVolumeSource{ - Path: hostPath, + Path: resolvedHostPath, Type: &captureFolderHostPathType, }, }, @@ -1731,7 +1793,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { }, podEnv: []v1.EnvVar{ {Name: captureConstants.CaptureDurationEnvKey, Value: "1m0s"}, - {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: hostPath}, + {Name: string(captureConstants.CaptureOutputLocationEnvKeyHostPath), Value: resolvedHostPath}, {Name: captureConstants.CaptureNameEnvKey, Value: captureName}, {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, @@ -1808,7 +1870,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { } if tt.capture.Spec.OutputConfiguration.HostPath != nil { - job.Spec.Template.Annotations[captureConstants.CaptureHostPathAnnotationKey] = hostPath + job.Spec.Template.Annotations[captureConstants.CaptureHostPathAnnotationKey] = resolvedHostPath } cmpOption := cmp.Options{ @@ -1835,7 +1897,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs_JobNumLimit(t *testing.T timestamp := file.Now() captureName := "capture-test" - hostPath := "/tmp/capture" + hostPath := "capture" cases := []struct { name string capture retinav1alpha1.Capture diff --git a/pkg/capture/hostpath_validation.go b/pkg/capture/hostpath_validation.go new file mode 100644 index 0000000000..e42d6d548f --- /dev/null +++ b/pkg/capture/hostpath_validation.go @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "errors" + "fmt" + "path/filepath" + "regexp" + "strings" +) + +// DefaultHostPathBaseDir is the safe default location under which Capture CRs may +// place captured artifacts on a node when no operator-level base directory is configured. +const DefaultHostPathBaseDir = "/var/log/retina/captures" + +var ( + // ErrHostPathEmpty is returned when the supplied HostPath is empty. + ErrHostPathEmpty = errors.New("hostPath is empty") + // ErrHostPathAbsolute is returned when the supplied HostPath is absolute. The + // CR field is a subpath name only; it must not contain a leading separator + // (POSIX or Windows) or a drive-letter prefix. + ErrHostPathAbsolute = errors.New("hostPath must be a relative subpath name, not an absolute path") + // ErrHostPathTraversal is returned when the supplied HostPath contains a parent-directory traversal. + ErrHostPathTraversal = errors.New("hostPath must not contain '..' path segments") + // ErrHostPathEscapesBase is a defense-in-depth error returned when, after + // joining and cleaning, the resulting path would lie outside the configured base directory. + ErrHostPathEscapesBase = errors.New("hostPath resolves outside the configured base directory") + // ErrHostPathBaseDir is returned when the operator-provided base directory is not usable. + ErrHostPathBaseDir = errors.New("invalid hostPath base directory") +) + +// winDriveLetter matches a Windows drive-letter prefix such as "C:\" or "c:/". +var winDriveLetter = regexp.MustCompile(`^[A-Za-z]:[\\/]`) + +// validateHostPath ensures that the user-supplied HostPath from a Capture CR is safe +// to mount into the privileged capture pod and returns the absolute, cleaned path the +// capture artifacts will live at on the node. +// +// The CR's HostPath is treated as a relative subpath name and joined under baseDir; +// CR authors cannot escape that directory. Rules: +// +// - The path must be non-empty. +// - The path must not be absolute (no leading "/" or "\\", no Windows drive letter). +// - The path must not contain any ".." segment, checked both on the raw input and +// after filepath.Clean. +// - As defense in depth, the joined path must still resolve under baseDir. +// +// If baseDir is empty, DefaultHostPathBaseDir is used. +func validateHostPath(raw, baseDir string) (string, error) { + if raw == "" { + return "", ErrHostPathEmpty + } + + if baseDir == "" { + baseDir = DefaultHostPathBaseDir + } + cleanedBase := filepath.Clean(baseDir) + if !filepath.IsAbs(cleanedBase) { + return "", fmt.Errorf("%w: %q must be absolute", ErrHostPathBaseDir, baseDir) + } + + // Reject absolute paths up front, in both POSIX and Windows styles, so existing + // CRs that supplied an absolute host path fail loudly instead of being silently + // rewritten by filepath.Join. + if filepath.IsAbs(raw) || + strings.HasPrefix(raw, "/") || + strings.HasPrefix(raw, `\`) || + winDriveLetter.MatchString(raw) { + return "", fmt.Errorf("%w: %q", ErrHostPathAbsolute, raw) + } + + // Reject literal ".." segments before cleaning so traversal attempts are + // rejected even if filepath.Clean would normalize them away. + if containsParentSegment(raw) { + return "", fmt.Errorf("%w: %q", ErrHostPathTraversal, raw) + } + + cleanedSub := filepath.Clean(raw) + if cleanedSub == "." || cleanedSub == "" { + return "", ErrHostPathEmpty + } + if filepath.IsAbs(cleanedSub) || strings.HasPrefix(cleanedSub, "/") || strings.HasPrefix(cleanedSub, `\`) { + return "", fmt.Errorf("%w: %q", ErrHostPathAbsolute, raw) + } + if containsParentSegment(cleanedSub) { + return "", fmt.Errorf("%w: %q", ErrHostPathTraversal, raw) + } + + joined := filepath.Clean(filepath.Join(cleanedBase, cleanedSub)) + rel, err := filepath.Rel(cleanedBase, joined) + if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) { + return "", fmt.Errorf("%w: %q resolves to %q (base %q)", ErrHostPathEscapesBase, raw, joined, cleanedBase) + } + + return joined, nil +} + +// containsParentSegment returns true if any path segment of p (split on either +// forward or back slashes) equals "..". +func containsParentSegment(p string) bool { + for _, seg := range strings.FieldsFunc(p, func(r rune) bool { return r == '/' || r == '\\' }) { + if seg == ".." { + return true + } + } + return false +} diff --git a/pkg/capture/hostpath_validation_test.go b/pkg/capture/hostpath_validation_test.go new file mode 100644 index 0000000000..e845fa28cb --- /dev/null +++ b/pkg/capture/hostpath_validation_test.go @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "errors" + "strings" + "testing" +) + +func TestValidateHostPath(t *testing.T) { + const base = "/var/log/retina/captures" + + tests := []struct { + name string + raw string + baseDir string + want string + wantErr error + }{ + // rejection cases + {name: "empty", raw: "", baseDir: base, wantErr: ErrHostPathEmpty}, + {name: "dot only resolves to empty", raw: ".", baseDir: base, wantErr: ErrHostPathEmpty}, + {name: "absolute posix", raw: "/tmp/retina", baseDir: base, wantErr: ErrHostPathAbsolute}, + {name: "absolute posix with traversal", raw: "/var/log/../etc", baseDir: base, wantErr: ErrHostPathAbsolute}, + {name: "absolute windows backslash", raw: `\tmp\retina`, baseDir: base, wantErr: ErrHostPathAbsolute}, + {name: "absolute windows drive letter", raw: `C:\evil`, baseDir: base, wantErr: ErrHostPathAbsolute}, + {name: "absolute windows drive letter forward", raw: "c:/evil", baseDir: base, wantErr: ErrHostPathAbsolute}, + {name: "traversal raw", raw: "../etc", baseDir: base, wantErr: ErrHostPathTraversal}, + {name: "traversal mid", raw: "foo/../bar", baseDir: base, wantErr: ErrHostPathTraversal}, + {name: "traversal backslash", raw: `foo\..\bar`, baseDir: base, wantErr: ErrHostPathTraversal}, + {name: "traversal escaping base", raw: "../../etc", baseDir: base, wantErr: ErrHostPathTraversal}, + + // acceptance cases + {name: "bare name", raw: "retina", baseDir: base, want: base + "/retina"}, + {name: "nested subpath", raw: "job1/out", baseDir: base, want: base + "/job1/out"}, + {name: "trailing slash cleaned", raw: "job/", baseDir: base, want: base + "/job"}, + {name: "redundant separators cleaned", raw: "job//./out", baseDir: base, want: base + "/job/out"}, + {name: "root base dir accepts subpath", raw: "captures", baseDir: "/", want: "/captures"}, + {name: "root base dir accepts nested subpath", raw: "a/b", baseDir: "/", want: "/a/b"}, + + // defaulting + {name: "default base used when empty", raw: "x", baseDir: "", want: DefaultHostPathBaseDir + "/x"}, + + // invalid base + {name: "relative base rejected", raw: "x", baseDir: "captures", wantErr: ErrHostPathBaseDir}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := validateHostPath(tt.raw, tt.baseDir) + if tt.wantErr != nil { + if !errors.Is(err, tt.wantErr) { + t.Fatalf("expected error %v, got %v", tt.wantErr, err) + } + if got != "" { + t.Fatalf("expected empty result on error, got %q", got) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got != tt.want { + t.Fatalf("got %q, want %q", got, tt.want) + } + }) + } +} + +// TestValidateHostPath_ResultsAlwaysUnderBase is a property-style assertion: for +// every accepted input across a small enumerated set, the cleaned result must be +// the base or be nested under base + separator. This guards against future +// regressions where validation might let through an input whose joined form +// escapes the base directory. +func TestValidateHostPath_ResultsAlwaysUnderBase(t *testing.T) { + const base = "/var/log/retina/captures" + inputs := []string{ + "a", "a/b", "a/b/c", "x.pcap", "deep/nested/path/name", + "with-hyphen", "with_underscore", "with.dots", + } + for _, in := range inputs { + t.Run(in, func(t *testing.T) { + got, err := validateHostPath(in, base) + if err != nil { + t.Fatalf("unexpected error for %q: %v", in, err) + } + if got != base && !strings.HasPrefix(got, base+"/") { + t.Fatalf("%q resolved to %q which is not under %q", in, got, base) + } + }) + } +} diff --git a/pkg/capture/utils/annotations.go b/pkg/capture/utils/annotations.go index 6723270843..b9f72cf253 100644 --- a/pkg/capture/utils/annotations.go +++ b/pkg/capture/utils/annotations.go @@ -9,14 +9,21 @@ import ( "github.com/microsoft/retina/pkg/capture/file" ) -func GetPodAnnotationsFromCapture(capture *retinav1alpha1.Capture) map[string]string { +// GetPodAnnotationsFromCapture builds the capture pod annotations. resolvedHostPath, +// when non-empty, is written as the CaptureHostPathAnnotationKey value (the on-node +// path actually mounted into the capture pod). When empty, the raw value from the +// Capture spec is used as a fallback (e.g. when called from contexts where the +// host path has not been resolved yet). +func GetPodAnnotationsFromCapture(capture *retinav1alpha1.Capture, resolvedHostPath string) map[string]string { annotations := map[string]string{ captureConstants.CaptureFilenameAnnotationKey: capture.Name, } if capture.Status.StartTime != nil { annotations[captureConstants.CaptureTimestampAnnotationKey] = file.TimeToString(capture.Status.StartTime) } - if capture.Spec.OutputConfiguration.HostPath != nil { + if resolvedHostPath != "" { + annotations[captureConstants.CaptureHostPathAnnotationKey] = resolvedHostPath + } else if capture.Spec.OutputConfiguration.HostPath != nil { annotations[captureConstants.CaptureHostPathAnnotationKey] = *capture.Spec.OutputConfiguration.HostPath } return annotations diff --git a/pkg/capture/utils/annotations_test.go b/pkg/capture/utils/annotations_test.go new file mode 100644 index 0000000000..eb1161018e --- /dev/null +++ b/pkg/capture/utils/annotations_test.go @@ -0,0 +1,121 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package utils + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" + captureConstants "github.com/microsoft/retina/pkg/capture/constants" + "github.com/microsoft/retina/pkg/capture/file" +) + +func TestGetPodAnnotationsFromCapture(t *testing.T) { + startTime := &metav1.Time{Time: time.Date(2026, 5, 20, 10, 0, 0, 0, time.UTC)} + rawHostPath := "my-capture" + resolvedHostPath := "/var/log/retina/captures/my-capture" + + captureWithHostPath := func() *retinav1alpha1.Capture { + hp := rawHostPath + return &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{Name: "cap1"}, + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{HostPath: &hp}, + }, + Status: retinav1alpha1.CaptureStatus{StartTime: startTime}, + } + } + + cases := []struct { + name string + capture *retinav1alpha1.Capture + resolvedHostPath string + wantHostPathAnn string // empty means annotation must be absent + }{ + { + // This is the case that caused the download bug: capture is created + // with a relative subpath, the operator resolves it to an absolute + // on-node path, and the annotation must carry the resolved value + // (because `kubectl retina capture download` mounts it verbatim). + name: "resolved path wins over raw spec value", + capture: captureWithHostPath(), + resolvedHostPath: resolvedHostPath, + wantHostPathAnn: resolvedHostPath, + }, + { + // Fallback path for callers that don't have a resolved value (e.g. + // CLI helpers that only see the CR). The raw spec value is used. + name: "raw spec value used when resolved is empty", + capture: captureWithHostPath(), + resolvedHostPath: "", + wantHostPathAnn: rawHostPath, + }, + { + // Defense-in-depth: even if the spec has no HostPath, an explicit + // resolved value should still be written (callers own the choice). + name: "resolved path is written even when spec.HostPath is nil", + capture: &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{Name: "cap2"}, + Status: retinav1alpha1.CaptureStatus{StartTime: startTime}, + }, + resolvedHostPath: resolvedHostPath, + wantHostPathAnn: resolvedHostPath, + }, + { + name: "no HostPath annotation when neither resolved nor spec is set", + capture: &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{Name: "cap3"}, + Status: retinav1alpha1.CaptureStatus{StartTime: startTime}, + }, + resolvedHostPath: "", + wantHostPathAnn: "", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got := GetPodAnnotationsFromCapture(tc.capture, tc.resolvedHostPath) + + // Filename annotation is always set to the capture name. + assert.Equal(t, tc.capture.Name, got[captureConstants.CaptureFilenameAnnotationKey]) + + if tc.wantHostPathAnn == "" { + _, ok := got[captureConstants.CaptureHostPathAnnotationKey] + assert.False(t, ok, "HostPath annotation should be absent") + } else { + assert.Equal(t, tc.wantHostPathAnn, got[captureConstants.CaptureHostPathAnnotationKey]) + } + }) + } +} + +func TestGetPodAnnotationsFromCapture_TimestampOnlyWhenStartTimeSet(t *testing.T) { + hp := "my-capture" + base := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{Name: "cap"}, + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{HostPath: &hp}, + }, + } + + t.Run("no StartTime -> no timestamp annotation", func(t *testing.T) { + got := GetPodAnnotationsFromCapture(base, "") + _, ok := got[captureConstants.CaptureTimestampAnnotationKey] + assert.False(t, ok) + }) + + t.Run("StartTime set -> timestamp annotation populated", func(t *testing.T) { + ts := &metav1.Time{Time: time.Date(2026, 5, 20, 10, 0, 0, 0, time.UTC)} + c := base.DeepCopy() + c.Status.StartTime = ts + + got := GetPodAnnotationsFromCapture(c, "") + require.Equal(t, file.TimeToString(ts), got[captureConstants.CaptureTimestampAnnotationKey]) + }) +} diff --git a/pkg/config/capture.go b/pkg/config/capture.go index c20899707b..9aea82a85d 100644 --- a/pkg/config/capture.go +++ b/pkg/config/capture.go @@ -27,4 +27,12 @@ type CaptureConfig struct { EnableManagedStorageAccount bool `yaml:"enableManagedStorageAccount"` // AzureCredentialConfig indicates the path of Azure credential configuration file. AzureCredentialConfig string `yaml:"azureCredentialConfig"` + + // CaptureHostPathBaseDir is the absolute, operator-controlled directory on every + // node under which Capture CRs may write artifacts. The user-supplied + // OutputConfiguration.HostPath is treated as a relative subpath name and joined + // under this directory. CR authors cannot influence the base, so they cannot + // place artifacts anywhere else on the node filesystem. + // If unset, the operator defaults to /var/log/retina/captures. + CaptureHostPathBaseDir string `yaml:"captureHostPathBaseDir"` } diff --git a/pkg/controllers/operator/capture/controller.go b/pkg/controllers/operator/capture/controller.go index 78d9a5d8bd..1e83311610 100644 --- a/pkg/controllers/operator/capture/controller.go +++ b/pkg/controllers/operator/capture/controller.go @@ -226,7 +226,6 @@ func (cr *CaptureReconciler) createJobsFromCapture(ctx context.Context, capture jobs, err := cr.captureToPodTranslator.TranslateCaptureToJobs(ctx, capture) if err != nil { - cr.logger.Error("Failed to translate Capture to jobs", zap.Error(err), zap.String("Capture", captureRef.String())) var errorReason string switch err.(type) { case pkgcapture.CaptureJobNumExceedLimitError: diff --git a/samples/capture/capture-specific-pod-on-a-node.yaml b/samples/capture/capture-specific-pod-on-a-node.yaml index d404e0ebfe..bcb697adcb 100644 --- a/samples/capture/capture-specific-pod-on-a-node.yaml +++ b/samples/capture/capture-specific-pod-on-a-node.yaml @@ -25,5 +25,5 @@ spec: outputConfiguration: # the artifact will be copied to hostpath # and uploaded to azure storage account - hostPath: "/tmp/retina" + hostPath: "retina" blobUpload: blobsassecret diff --git a/samples/capture/node-s3upload-aws.yaml b/samples/capture/node-s3upload-aws.yaml index 9714249200..1a5bdd91b3 100644 --- a/samples/capture/node-s3upload-aws.yaml +++ b/samples/capture/node-s3upload-aws.yaml @@ -19,7 +19,7 @@ spec: ], } outputConfiguration: - hostPath: "/tmp/retina" + hostPath: "retina" s3Upload: bucket: retina-bucket region: ap-northeast-2 diff --git a/samples/capture/node-s3upload-minio.yaml b/samples/capture/node-s3upload-minio.yaml index a6199960f3..f533220951 100644 --- a/samples/capture/node-s3upload-minio.yaml +++ b/samples/capture/node-s3upload-minio.yaml @@ -19,7 +19,7 @@ spec: ], } outputConfiguration: - hostPath: "/tmp/retina" + hostPath: "retina" s3Upload: bucket: retina-bucket endpoint: https://play.min.io:9000 diff --git a/samples/capture/nodeblobupload.yaml b/samples/capture/nodeblobupload.yaml index 80cae35c01..1b8e26d615 100644 --- a/samples/capture/nodeblobupload.yaml +++ b/samples/capture/nodeblobupload.yaml @@ -19,5 +19,5 @@ spec: ], } outputConfiguration: - hostPath: "/tmp/retina" + hostPath: "retina" blobUpload: blobsassecret diff --git a/samples/capture/podblobupload.yaml b/samples/capture/podblobupload.yaml index 88260f86c4..97e3a6141e 100644 --- a/samples/capture/podblobupload.yaml +++ b/samples/capture/podblobupload.yaml @@ -16,5 +16,5 @@ spec: outputConfiguration: # the artifact will be copied to hostpath # and uploaded to azure storage account - hostPath: "/tmp/retina" + hostPath: "retina" blobUpload: blobsassecret From b57a8aeb6669be427d02f162b35eee0e4c6de43f Mon Sep 17 00:00:00 2001 From: Mereta Date: Thu, 21 May 2026 14:07:23 +0100 Subject: [PATCH 427/448] fix(capture-cve): Retina capture tcpdump sanitization (#2322) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Security Enhancement - Command Injection Fix & API Modernization ## Vulnerability Summary ### Original Issue The `tcpdumpFilter` field in Capture CRD allowed command injection through malicious filter values: - **Attack Vector**: Attackers with `captures.retina.sh` create permission could escalate to node-root/SYSTEM access - **Example Exploit**: `tcpdumpFilter: "-z /evil.sh"` would execute arbitrary scripts with root privileges - **Platforms Affected**: Both Linux (tcpdump) and Windows (netsh) implementations ### Attack Surface 1. **Linux tcpdump**: Flag injection via `-z`, `-w`, `-r`, `-G` and other dangerous flags 2. **Windows netsh**: Shell metacharacter injection via `&`, `|`, `;`, `$()`, etc. 3. **Filter bypass**: Whitespace-only or empty filters to bypass validation --- ## Overview Security fix with API modernization - deprecated the vulnerable `tcpdumpFilter` field in favor of type-safe structured options under `captureOption`. **Note:** Despite the field name, Windows nodes **do not use tcpdump**. The filter fields are interpreted as: - **Unix/Linux**: BPF filter syntax for tcpdump - **Windows**: netsh filter syntax for netsh trace **Key Changes:** 1. **New Structured API**: Introduced `captureOption.pcapFilter` field with enum-based flags for type-safe capture configuration 2. **NEW: 3 Enum Fields** for tcpdump display options (Linux/Unix only): - `verbosity`: `""` (normal), `"verbose"` (tcpdump -v), `"extra"` (tcpdump -vv), `"max"` (tcpdump -vvv) - `printDataFormat`: `""` (none), `"hex"` (tcpdump -x), `"hex-with-link"` (tcpdump -xx), `"ascii"` (tcpdump -A), `"ascii-with-link"` (tcpdump -AA) - `timestampFormat`: `""` (default), `"none"` (tcpdump -t), `"unformatted"` (tcpdump -tt), `"delta"` (tcpdump -ttt), `"date"` (tcpdump -tttt), `"delta-since-first"` (tcpdump -ttttt) 3. **CLI Enhancement**: Added enum-based flags to `kubectl retina capture create` (`--verbosity`, `--print-data`, `--timestamp-format`) 4. **Unix/Linux - BPF Syntax Validation**: Uses `tcpdump -d` to validate filter syntax before capture execution 5. **Windows - Regex Validation**: Blocks shell metacharacters in netsh trace filters (enum flags ignored on Windows) 6. **Backward Compatibility**: Deprecated `tcpdumpFilter` still works with validation, but `pcapFilter` takes precedence 7. **Defense in Depth**: Multiple independent validation layers block dangerous content and malformed filters 8. **Clear Error Messages**: Users receive specific feedback about validation failures --- ## Implementation ### New Structured API **CRD Changes** (`crd/api/v1alpha1/capture_types.go`) - **New Field**: `captureOption.pcapFilter` (string) - BPF/netsh filter syntax (replaces `tcpdumpFilter`) - **New Enum Fields** (**Linux/Unix only**) - Type-safe options for tcpdump display formatting: **`verbosity` (string enum)** - Controls tcpdump verbosity level (mutually exclusive): - `""` → Normal output (no -v flags) - `"verbose"` → `-v` (verbose output) - `"extra"` → `-vv` (extra verbose output) - `"max"` → `-vvv` (maximum verbose output) - **kubebuilder validation**: `+kubebuilder:validation:Enum="";verbose;extra;max` **`printDataFormat` (string enum)** - Controls packet data printing format (mutually exclusive): - `""` → No packet data printing - `"hex"` → `-x` (hex packet data) - `"hex-with-link"` → `-xx` (hex with link-level headers) - `"ascii"` → `-A` (ASCII packet data) - `"ascii-with-link"` → `-AA` (ASCII with link-level headers) - **kubebuilder validation**: `+kubebuilder:validation:Enum="";hex;hex-with-link;ascii;ascii-with-link` **`timestampFormat` (string enum)** - Controls timestamp display format (mutually exclusive): - `""` → Default timestamp format - `"none"` → `-t` (no timestamps) - `"unformatted"` → `-tt` (Unix timestamp) - `"delta"` → `-ttt` (time since previous packet) - `"date"` → `-tttt` (date and time) - `"delta-since-first"` → `-ttttt` (time since first packet) - **kubebuilder validation**: `+kubebuilder:validation:Enum="";none;unformatted;delta;date;delta-since-first` - **Remaining Boolean Flags** (non-mutually-exclusive options): - `noPromiscuous` → `-p` (don't capture in promiscuous mode) - `packetBuffered` → `-U` (packet-buffered output) - `immediateMode` → `--immediate-mode` (immediate packet delivery) - `noResolveDNS` → `-n` (don't resolve addresses) - `noResolvePort` → `-nn` (don't resolve addresses or ports) - `printLinkHeader` → `-e` (print link-level header) - `quietOutput` → `-q` (quick/quiet output) - `absoluteSeq` → `-S` (absolute TCP sequence numbers) - `dontVerifyChecksum` → `-K` (don't verify checksums) - **Note**: All flags are ignored on Windows (netsh trace has no equivalent formatting options) - **Deprecated Field**: `tcpdumpFilter` (still works for backward compatibility) - **Precedence**: `pcapFilter` takes precedence over `tcpdumpFilter` when both are set - **MaxLength**: 1024 characters on filter fields prevents resource exhaustion ### Three Validation Layers **Layer 1: Type Safety** (CRD Level) - **Enum validation**: Kubebuilder annotations enforce valid enum values at API server level - **Mutually exclusive**: Single enum field prevents conflicting options (e.g., can't set both "verbose" and "max") - **String-based enums**: Direct mapping to tcpdump flags with clear semantics - No user-provided flags can reach the command line **Layer 2: Filter Syntax Validation** (Unix/Linux - `network_capture_unix.go`) - Validates BPF filter syntax using `tcpdump -d` before execution - Catches invalid ports, unknown protocols, malformed syntax - Prevents injection attempts disguised as filter syntax **Layer 3: Legacy Path Validation** (Backward Compatibility) - Deprecated `tcpdumpFilter` still validated with warning logs - Same BPF/netsh syntax validation applied ### Windows: Filter Validation Only **Implementation** (`network_capture_win.go`) - **Uses netsh trace** (tcpdump is not available on Windows) - **Enum flags not supported** - netsh trace does not have formatting options like tcpdump - Enum and boolean flags are silently ignored on Windows (no error, but no effect) - Output formatting happens post-capture using tools like Network Monitor or Wireshark - **Filter validation only**: `pcapFilter` interpreted as netsh filter syntax (key=value format, e.g., `IPv4.Address=10.0.0.1`) - Regex pattern validates filter contains only safe characters: `^[A-Za-z0-9.=():, ]+$` - **Blocks shell metacharacters**: `&`, `|`, `^`, `<`, `>`, `%`, `"`, `'`, `;`, `$`, `` ` ``, `\`, newlines - Filter tokens split on spaces and passed as separate arguments to netsh **Security Features:** - Uses `exec.Command` with explicit Args (no shell parsing) - Validates filter content before adding to command - Clear error message: "filter contains invalid characters; only alphanumeric, dots, colons, parentheses, commas, equals, and spaces are allowed" --- ## Test Results **7 test cases covering new enum-based API, backward compatibility, and CLI:** | Test ID | Test Case | Configuration | Expected | Result | |---------|-----------|---------------|----------|--------| | **TC-01** | Enum - Verbose + Hex + Date | `verbosity: "verbose"` + `printDataFormat: "hex"` + `timestampFormat: "date"` + `pcapFilter: "tcp port 443"` | `-v -x -tttt tcp port 443` | ✅ PASS | | **TC-02** | Enum - Max Verbosity + ASCII + Delta | `verbosity: "max"` + `printDataFormat: "ascii"` + `timestampFormat: "delta"` + other flags | `-vvv -A -ttt tcp port 443` | ✅ PASS | | **TC-03** | Enum - Extra Verbose + Hex with Link + No Timestamps | `verbosity: "extra"` + `printDataFormat: "hex-with-link"` + `timestampFormat: "none"` | `-vv -xx -t tcp` | ✅ PASS | | **TC-04** | Enum - Default Values (Empty Strings) | `verbosity: ""` + `printDataFormat: ""` + `timestampFormat: ""` + boolean flags | No enum flags, only boolean flags applied | ✅ PASS | | **TC-05** | CLI - Enum Flags | `kubectl retina capture create --verbosity verbose --print-data hex --timestamp-format date` | CRD created with enum values set correctly | ✅ PASS | | **TC-06** | Deprecated Field Still Works | `tcpdumpFilter: "icmp"` (no enums) | Warning logged + `icmp` filter applied | ✅ PASS | | **TC-07** | Precedence Test | `tcpdumpFilter: "tcp port 8080"` + `pcapFilter: "tcp port 80"` | `pcapFilter` used: `tcp port 80` | ✅ PASS | | **TC-08** | '-' rejection in pcapFilter & tcpdumpFilter | `tcpdumpFilter: "-n tcp port 8080"` + `pcapFilter: "-n tcp port 80"` | Validation fail | ✅ PASS | **Overall Results:** - **New Enum-Based API**: 4/4 tests passed (TC-01, TC-02, TC-03, TC-04) - **CLI with Enums**: 1/1 test passed (TC-05) - **Backward Compatibility**: 1/1 test passed (TC-06) - **Precedence Logic**: 1/1 test passed (TC-07) - **Overall**: 7/7 tests passed (100%) CLI command: ``` /usr/local/bin/kubectl-retina capture create \ --name test-enum-cli-v3 \ --duration 3m \ --verbosity verbose \ --print-data hex \ --timestamp-format date \ --no-resolve-dns \ --no-resolve-port \ --host-path "/tmp/retina/cli-test" \ --node-selectors "kubernetes.io/os=linux" ``` One of CRD's with filters: image **Screenshots:** TC-05: CLI with Enum Flags: image TC-06: Deprecated Filter: image TC-07: Filter Precedence: image TC-01: Filter Flags: image TC-08: Disallow '-' flags tcpdumpfilter: image pcapfilter: image CRD: image **Test Files for Validation:** - `test-enum-capture.yaml` - Comprehensive example with all three enum fields set - `test-enum-examples.yaml` - Five different examples showing various enum combinations - `TESTING-ENUMS.md` - Complete testing guide with enum→tcpdump flag mapping table and validation tests --- ## Bug Fix: Filters Concatenated Without AND Operator ### Issue Old code concatenated user and system filters without `and` operator, creating invalid BPF syntax. Only true for when `tcpdumpfilter` and `podselector` or `include/exclude` combination was present. **Old (INVALID):** ```bash tcpdump -i any tcp port 443 ((host 192.168.0.1) or (host 10.244.0.5)) ``` **New (VALID):** ```bash tcpdump -i any "tcp port 443 and ((host 192.168.0.1) or (host 10.244.0.5))" ``` ### Impact - User filters now work with system filters - Proper BPF combination using `and` operator - Both new `PcapFilter` and deprecated `TcpdumpFilter` functional --- ## Design Decisions ### Why Enum-Based Fields for Display Options? Enums provide a cleaner API for mutually exclusive tcpdump options: - **Mutually Exclusive by Design**: Single field prevents conflicting options (e.g., can't set both "verbose" and "max") - **API Validation**: Kubebuilder enum validation enforces valid values at Kubernetes API server level - **Clear Intent**: `verbosity: "max"` is self-documenting - **Type Safety**: Enum values constrained to predefined safe strings, preventing command injection --- ## Impact **No Breaking Changes** - New enum fields added alongside existing options **What's New:** - 3 enum fields for tcpdump display options: `verbosity`, `printDataFormat`, `timestampFormat` - CLI flags: `--verbosity`, `--print-data`, `--timestamp-format` - Kubebuilder enum validation at API level - Prevents setting conflicting options (e.g., both verbose and max verbosity) **Security:** - Type-safe enum values prevent command injection - Filter syntax validation using `tcpdump -d` (Linux) or regex (Windows) - No user-provided flags reach command line --------- Signed-off-by: mereta --- cli/cmd/capture/capture.go | 84 +++ cli/cmd/capture/create.go | 130 +++- cli/cmd/capture/enums_test.go | 470 +++++++++++++ crd/api/v1alpha1/capture_types.go | 88 ++- crd/api/v1alpha1/zz_generated.deepcopy.go | 65 ++ .../helm/retina/crds/retina.sh_captures.yaml | 106 ++- .../crds/retina.sh_metricsconfigurations.yaml | 2 +- .../crds/retina.sh_retinaendpoints.yaml | 2 +- .../crds/retina.sh_tracesconfigurations.yaml | 2 +- docs/04-Captures/02-cli.md | 58 +- docs/05-Concepts/CRDs/Capture.md | 154 ++++- pkg/capture/constants/job_env.go | 2 + pkg/capture/crd_to_job.go | 73 +++ pkg/capture/crd_to_job_test.go | 113 +++- pkg/capture/provider/network_capture_test.go | 617 +++++++++++++++++- pkg/capture/provider/network_capture_unix.go | 156 ++++- pkg/capture/provider/network_capture_win.go | 68 +- .../provider/network_capture_win_test.go | 116 ++++ 18 files changed, 2207 insertions(+), 99 deletions(-) create mode 100644 cli/cmd/capture/enums_test.go create mode 100644 pkg/capture/provider/network_capture_win_test.go diff --git a/cli/cmd/capture/capture.go b/cli/cmd/capture/capture.go index a1457c2c73..32af373e5f 100644 --- a/cli/cmd/capture/capture.go +++ b/cli/cmd/capture/capture.go @@ -4,6 +4,8 @@ package capture import ( + "errors" + "fmt" "time" "github.com/spf13/cobra" @@ -11,6 +13,74 @@ import ( "k8s.io/client-go/kubernetes" ) +var ( + ErrInvalidVerbosityLevel = errors.New("invalid verbosity level") + ErrInvalidTimestampFormat = errors.New("invalid timestamp format") + ErrInvalidPrintDataFormat = errors.New("invalid print data format") + ErrBPFFilterEmpty = errors.New("BPF filter cannot be empty or whitespace-only") + ErrBPFFilterContainsFlag = errors.New("BPF filter contains flag which is not allowed") +) + +// VerbosityLevel represents the verbosity level for packet capture output +type VerbosityLevel string + +const ( + VerbosityNormal VerbosityLevel = "" // Default, no extra verbosity + VerbosityVerbose VerbosityLevel = "verbose" // tcpdump -v + VerbosityExtra VerbosityLevel = "extra" // tcpdump -vv + VerbosityMax VerbosityLevel = "max" // tcpdump -vvv +) + +func (v VerbosityLevel) Validate() error { + switch v { + case VerbosityNormal, VerbosityVerbose, VerbosityExtra, VerbosityMax: + return nil + default: + return fmt.Errorf("%w: %s (valid: verbose, extra, max)", ErrInvalidVerbosityLevel, v) + } +} + +// TimestampFormat represents the timestamp format for packet capture output +type TimestampFormat string + +const ( + TimestampDefault TimestampFormat = "" // Default formatted timestamp + TimestampNone TimestampFormat = "none" // tcpdump -t + TimestampUnformatted TimestampFormat = "unformatted" // tcpdump -tt (Unix epoch) + TimestampDelta TimestampFormat = "delta" // tcpdump -ttt (delta between packets) + TimestampDate TimestampFormat = "date" // tcpdump -tttt (with date) + TimestampDeltaSinceFirst TimestampFormat = "delta-since-first" // tcpdump -ttttt (delta since first) +) + +func (t TimestampFormat) Validate() error { + switch t { + case TimestampDefault, TimestampNone, TimestampUnformatted, TimestampDelta, TimestampDate, TimestampDeltaSinceFirst: + return nil + default: + return fmt.Errorf("%w: %s (valid: none, unformatted, delta, date, delta-since-first)", ErrInvalidTimestampFormat, t) + } +} + +// PrintDataFormat represents the format for printing packet data +type PrintDataFormat string + +const ( + PrintDataNone PrintDataFormat = "" // Default, no data printing + PrintDataHex PrintDataFormat = "hex" // tcpdump -x (hex only) + PrintDataHexWithLink PrintDataFormat = "hex-with-link" // tcpdump -xx (hex with link header) + PrintDataASCII PrintDataFormat = "ascii" // tcpdump -A (ASCII only) + PrintDataASCIIWithLink PrintDataFormat = "ascii-with-link" // tcpdump -AA (ASCII with link header) +) + +func (p PrintDataFormat) Validate() error { + switch p { + case PrintDataNone, PrintDataHex, PrintDataHexWithLink, PrintDataASCII, PrintDataASCIIWithLink: + return nil + default: + return fmt.Errorf("%w: %s (valid: hex, hex-with-link, ascii, ascii-with-link)", ErrInvalidPrintDataFormat, p) + } +} + type Opts struct { genericclioptions.ConfigFlags Name *string @@ -39,7 +109,21 @@ type Opts struct { s3Path string s3Region string s3SecretAccessKey string + // tcpdumpFilter is deprecated and will be removed. Use captureOption.pcapFilter and captureOption boolean flags for display options. tcpdumpFilter string + pcapFilter string + noPromiscuous bool + packetBuffered bool + immediateMode bool + noResolveDNS bool + noResolvePort bool + verbosityLevel VerbosityLevel + timestampFormat TimestampFormat + printDataFormat PrintDataFormat + printLinkHeader bool + quietOutput bool + absoluteSeq bool + dontVerifyChecksum bool } var opts = Opts{ diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index e9e512c460..a42d9c99d1 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -197,7 +197,22 @@ func NewCreateSubCommand(kubeClient kubernetes.Interface) *cobra.Command { Example: createExample, } + var verbosityStr, timestampStr, printDataStr string + createCapture.RunE = func(*cobra.Command, []string) error { + // Validate enum flags + opts.verbosityLevel = VerbosityLevel(verbosityStr) + if err := opts.verbosityLevel.Validate(); err != nil { + return err + } + opts.timestampFormat = TimestampFormat(timestampStr) + if err := opts.timestampFormat.Validate(); err != nil { + return err + } + opts.printDataFormat = PrintDataFormat(printDataStr) + if err := opts.printDataFormat.Validate(); err != nil { + return err + } return create(kubeClient) } @@ -224,12 +239,35 @@ func NewCreateSubCommand(kubeClient kubernetes.Interface) *cobra.Command { createCapture.Flags().StringVar(&opts.s3Path, "s3-path", DefaultS3Path, "Prefix path within the S3 bucket where captures will be stored") createCapture.Flags().StringVar(&opts.s3AccessKeyID, "s3-access-key-id", "", "S3 access key id to upload capture files") createCapture.Flags().StringVar(&opts.s3SecretAccessKey, "s3-secret-access-key", "", "S3 access secret key to upload capture files") - createCapture.Flags().StringVar(&opts.tcpdumpFilter, "tcpdump-filter", "", "Raw tcpdump flags which works only for Linux") + createCapture.Flags().StringVar(&opts.tcpdumpFilter, "tcpdump-filter", "", + "DEPRECATED and will be removed: Use --pcap-filter for BPF expressions. BPF filter expression without flags (e.g., 'host 10.0.0.1', 'tcp port 443')") + createCapture.Flags().StringVar(&opts.pcapFilter, "pcap-filter", "", + "BPF filter expression for packet filtering (e.g., 'host 10.0.0.1', 'tcp port 443'). See https://www.tcpdump.org/manpages/pcap-filter.7.html") createCapture.Flags().StringVar(&opts.interfaces, "interfaces", "", "Comma-separated list of network interfaces to capture on (e.g., eth0,eth1)") + + // Tcpdump boolean flags for capture behavior and display options + createCapture.Flags().BoolVar(&opts.noPromiscuous, "no-promiscuous", false, "Disable promiscuous mode (tcpdump -p flag)") + createCapture.Flags().BoolVar(&opts.packetBuffered, "packet-buffered", false, "Enable packet-buffered output (tcpdump -U flag)") + createCapture.Flags().BoolVar(&opts.immediateMode, "immediate-mode", false, "Enable immediate mode for packet capture (tcpdump --immediate-mode)") + createCapture.Flags().BoolVar(&opts.noResolveDNS, "no-resolve-dns", false, "Don't resolve hostnames (tcpdump -n flag)") + createCapture.Flags().BoolVar(&opts.noResolvePort, "no-resolve-port", false, "Don't resolve hostnames or port names (tcpdump -nn flag)") + createCapture.Flags().BoolVar(&opts.printLinkHeader, "print-link-header", false, "Print link-level headers (tcpdump -e flag)") + createCapture.Flags().BoolVar(&opts.quietOutput, "quiet-output", false, "Quick/quiet output mode (tcpdump -q flag)") + createCapture.Flags().BoolVar(&opts.absoluteSeq, "absolute-seq", false, "Print absolute TCP sequence numbers (tcpdump -S flag)") + createCapture.Flags().BoolVar(&opts.dontVerifyChecksum, "dont-verify-checksum", false, "Don't verify TCP checksums (tcpdump -K flag)") + + // Enum-based flags for mutually exclusive options + createCapture.Flags().StringVar(&verbosityStr, "verbosity", "", "Verbosity level: verbose, extra, max (tcpdump -v/-vv/-vvv)") + createCapture.Flags().StringVar(×tampStr, "timestamp-format", "", "Timestamp format: none, unformatted, delta, date, delta-since-first (tcpdump -t/-tt/-ttt/-tttt/-ttttt)") + createCapture.Flags().StringVar(&printDataStr, "print-data", "", "Print packet data: hex, hex-with-link, ascii, ascii-with-link (tcpdump -x/-xx/-A/-AA)") + + // Filters createCapture.Flags().StringVar(&opts.excludeFilter, "exclude-filter", "", "A comma-separated list of IP:Port pairs that are "+ "excluded from capturing network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") createCapture.Flags().StringVar(&opts.includeFilter, "include-filter", "", "A comma-separated list of IP:Port pairs that are "+ "used to filter capture network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:*") + + // Capture options createCapture.Flags().BoolVar(&opts.includeMetadata, "include-metadata", DefaultIncludeMetadata, "If true, collect static network metadata into capture file") createCapture.Flags().IntVar(&opts.jobNumLimit, "job-num-limit", DefaultJobNumLimit, "The maximum number of jobs can be created for each capture. 0 means no limit") createCapture.Flags().BoolVar(&opts.nowait, "no-wait", DefaultNowait, "Do not wait for the long-running capture job to finish") @@ -287,7 +325,38 @@ func deleteSecret(ctx context.Context, kubeClient kubernetes.Interface, secretNa return kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(ctx, *secretName, metav1.DeleteOptions{}) //nolint:wrapcheck //internal return } +// validateBPFFilter checks that a BPF filter string doesn't contain flags (tokens starting with '-'). +// This prevents command injection attacks by ensuring only BPF expressions are provided. +func validateBPFFilter(filter, filterName string) error { + if filter == "" { + return nil + } + + trimmed := strings.TrimSpace(filter) + if trimmed == "" { + return fmt.Errorf("%s: %w", filterName, ErrBPFFilterEmpty) + } + + // Check for flags (tokens starting with '-') + tokens := strings.Fields(trimmed) + for _, token := range tokens { + if strings.HasPrefix(token, "-") { + return fmt.Errorf("%s contains flag %q: %w", filterName, token, ErrBPFFilterContainsFlag) + } + } + + return nil +} + func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, error) { + // Validate filters early to provide immediate feedback + if err := validateBPFFilter(opts.tcpdumpFilter, "--tcpdump-filter"); err != nil { + return nil, err + } + if err := validateBPFFilter(opts.pcapFilter, "--pcap-filter"); err != nil { + return nil, err + } + timestamp := file.Now() capture := &retinav1alpha1.Capture{ @@ -398,6 +467,65 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti capture.Spec.CaptureConfiguration.CaptureOption.Interfaces = interfaceSlice } + // Set pcap-filter if provided + if opts.pcapFilter != "" { + capture.Spec.CaptureConfiguration.CaptureOption.PcapFilter = &opts.pcapFilter + } + + // Set boolean capture and display flags + if opts.noPromiscuous { + capture.Spec.CaptureConfiguration.CaptureOption.NoPromiscuous = &opts.noPromiscuous + } + + if opts.packetBuffered { + capture.Spec.CaptureConfiguration.CaptureOption.PacketBuffered = &opts.packetBuffered + } + + if opts.immediateMode { + capture.Spec.CaptureConfiguration.CaptureOption.ImmediateMode = &opts.immediateMode + } + + if opts.noResolveDNS { + capture.Spec.CaptureConfiguration.CaptureOption.NoResolveDNS = &opts.noResolveDNS + } + if opts.noResolvePort { + capture.Spec.CaptureConfiguration.CaptureOption.NoResolvePort = &opts.noResolvePort + } + + // Set verbosity level enum field based on CLI value + if opts.verbosityLevel != VerbosityNormal { + verbosityStr := string(opts.verbosityLevel) + capture.Spec.CaptureConfiguration.CaptureOption.Verbosity = &verbosityStr + } + + // Set print data format enum field based on CLI value + if opts.printDataFormat != PrintDataNone { + printDataStr := string(opts.printDataFormat) + capture.Spec.CaptureConfiguration.CaptureOption.PrintDataFormat = &printDataStr + } + + if opts.printLinkHeader { + capture.Spec.CaptureConfiguration.CaptureOption.PrintLinkHeader = &opts.printLinkHeader + } + + if opts.quietOutput { + capture.Spec.CaptureConfiguration.CaptureOption.QuietOutput = &opts.quietOutput + } + + if opts.absoluteSeq { + capture.Spec.CaptureConfiguration.CaptureOption.AbsoluteSeq = &opts.absoluteSeq + } + + // Set timestamp format enum field based on CLI value + if opts.timestampFormat != TimestampDefault { + timestampStr := string(opts.timestampFormat) + capture.Spec.CaptureConfiguration.CaptureOption.TimestampFormat = ×tampStr + } + + if opts.dontVerifyChecksum { + capture.Spec.CaptureConfiguration.CaptureOption.DontVerifyChecksum = &opts.dontVerifyChecksum + } + if opts.hostPath != "" { capture.Spec.OutputConfiguration.HostPath = &opts.hostPath } diff --git a/cli/cmd/capture/enums_test.go b/cli/cmd/capture/enums_test.go new file mode 100644 index 0000000000..5064432c04 --- /dev/null +++ b/cli/cmd/capture/enums_test.go @@ -0,0 +1,470 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "testing" +) + +func TestVerbosityLevel_Validate(t *testing.T) { + tests := []struct { + name string + level VerbosityLevel + wantErr bool + }{ + { + name: "empty string (normal) is valid", + level: VerbosityNormal, + wantErr: false, + }, + { + name: "verbose is valid", + level: VerbosityVerbose, + wantErr: false, + }, + { + name: "extra is valid", + level: VerbosityExtra, + wantErr: false, + }, + { + name: "max is valid", + level: VerbosityMax, + wantErr: false, + }, + { + name: "invalid value", + level: VerbosityLevel("invalid"), + wantErr: true, + }, + { + name: "v is invalid (should use verbose)", + level: VerbosityLevel("v"), + wantErr: true, + }, + { + name: "vvv is invalid (should use max)", + level: VerbosityLevel("vvv"), + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.level.Validate() + if (err != nil) != tt.wantErr { + t.Errorf("VerbosityLevel.Validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestVerbosityLevel_Constants(t *testing.T) { + tests := []struct { + name string + level VerbosityLevel + expected string + }{ + { + name: "normal is empty string", + level: VerbosityNormal, + expected: "", + }, + { + name: "verbose equals 'verbose'", + level: VerbosityVerbose, + expected: "verbose", + }, + { + name: "extra equals 'extra'", + level: VerbosityExtra, + expected: "extra", + }, + { + name: "max equals 'max'", + level: VerbosityMax, + expected: "max", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if string(tt.level) != tt.expected { + t.Errorf("VerbosityLevel constant = %q, want %q", tt.level, tt.expected) + } + }) + } +} + +func TestTimestampFormat_Validate(t *testing.T) { + tests := []struct { + name string + format TimestampFormat + wantErr bool + }{ + { + name: "empty string (default) is valid", + format: TimestampDefault, + wantErr: false, + }, + { + name: "none is valid", + format: TimestampNone, + wantErr: false, + }, + { + name: "unformatted is valid", + format: TimestampUnformatted, + wantErr: false, + }, + { + name: "delta is valid", + format: TimestampDelta, + wantErr: false, + }, + { + name: "date is valid", + format: TimestampDate, + wantErr: false, + }, + { + name: "delta-since-first is valid", + format: TimestampDeltaSinceFirst, + wantErr: false, + }, + { + name: "invalid value", + format: TimestampFormat("invalid"), + wantErr: true, + }, + { + name: "epoch is invalid (should use unformatted)", + format: TimestampFormat("epoch"), + wantErr: true, + }, + { + name: "default as string is invalid (should be empty)", + format: TimestampFormat("default"), + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.format.Validate() + if (err != nil) != tt.wantErr { + t.Errorf("TimestampFormat.Validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestTimestampFormat_Constants(t *testing.T) { + tests := []struct { + name string + format TimestampFormat + expected string + }{ + { + name: "default is empty string", + format: TimestampDefault, + expected: "", + }, + { + name: "none equals 'none'", + format: TimestampNone, + expected: "none", + }, + { + name: "unformatted equals 'unformatted'", + format: TimestampUnformatted, + expected: "unformatted", + }, + { + name: "delta equals 'delta'", + format: TimestampDelta, + expected: "delta", + }, + { + name: "date equals 'date'", + format: TimestampDate, + expected: "date", + }, + { + name: "delta-since-first equals 'delta-since-first'", + format: TimestampDeltaSinceFirst, + expected: "delta-since-first", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if string(tt.format) != tt.expected { + t.Errorf("TimestampFormat constant = %q, want %q", tt.format, tt.expected) + } + }) + } +} + +func TestPrintDataFormat_Validate(t *testing.T) { + tests := []struct { + name string + format PrintDataFormat + wantErr bool + }{ + { + name: "empty string (none) is valid", + format: PrintDataNone, + wantErr: false, + }, + { + name: "hex is valid", + format: PrintDataHex, + wantErr: false, + }, + { + name: "hex-with-link is valid", + format: PrintDataHexWithLink, + wantErr: false, + }, + { + name: "ascii is valid", + format: PrintDataASCII, + wantErr: false, + }, + { + name: "ascii-with-link is valid", + format: PrintDataASCIIWithLink, + wantErr: false, + }, + { + name: "invalid value", + format: PrintDataFormat("invalid"), + wantErr: true, + }, + { + name: "X is invalid (should use hex)", + format: PrintDataFormat("X"), + wantErr: true, + }, + { + name: "none as string is invalid (should be empty)", + format: PrintDataFormat("none"), + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.format.Validate() + if (err != nil) != tt.wantErr { + t.Errorf("PrintDataFormat.Validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestPrintDataFormat_Constants(t *testing.T) { + tests := []struct { + name string + format PrintDataFormat + expected string + }{ + { + name: "none is empty string", + format: PrintDataNone, + expected: "", + }, + { + name: "hex equals 'hex'", + format: PrintDataHex, + expected: "hex", + }, + { + name: "hex-with-link equals 'hex-with-link'", + format: PrintDataHexWithLink, + expected: "hex-with-link", + }, + { + name: "ascii equals 'ascii'", + format: PrintDataASCII, + expected: "ascii", + }, + { + name: "ascii-with-link equals 'ascii-with-link'", + format: PrintDataASCIIWithLink, + expected: "ascii-with-link", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if string(tt.format) != tt.expected { + t.Errorf("PrintDataFormat constant = %q, want %q", tt.format, tt.expected) + } + }) + } +} + +// TestEnumMapping_Verbosity tests that the enum values correctly map to their intended usage +func TestEnumMapping_Verbosity(t *testing.T) { + tests := []struct { + name string + cliFlag string + expectedEnum VerbosityLevel + tcpdumpFlag string // what tcpdump flag this should produce + }{ + { + name: "no flag means normal (no tcpdump verbosity)", + cliFlag: "", + expectedEnum: VerbosityNormal, + tcpdumpFlag: "(none)", + }, + { + name: "verbose produces -v", + cliFlag: "verbose", + expectedEnum: VerbosityVerbose, + tcpdumpFlag: "-v", + }, + { + name: "extra produces -vv", + cliFlag: "extra", + expectedEnum: VerbosityExtra, + tcpdumpFlag: "-vv", + }, + { + name: "max produces -vvv", + cliFlag: "max", + expectedEnum: VerbosityMax, + tcpdumpFlag: "-vvv", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + level := VerbosityLevel(tt.cliFlag) + if level != tt.expectedEnum { + t.Errorf("VerbosityLevel(%q) = %q, want %q", tt.cliFlag, level, tt.expectedEnum) + } + if err := level.Validate(); err != nil { + t.Errorf("VerbosityLevel(%q).Validate() error = %v", tt.cliFlag, err) + } + t.Logf("✓ --verbosity=%s → %s → tcpdump %s", tt.cliFlag, tt.expectedEnum, tt.tcpdumpFlag) + }) + } +} + +// TestEnumMapping_Timestamp tests that the enum values correctly map to their intended usage +func TestEnumMapping_Timestamp(t *testing.T) { + tests := []struct { + name string + cliFlag string + expectedEnum TimestampFormat + tcpdumpFlag string + }{ + { + name: "default means normal timestamps", + cliFlag: "", + expectedEnum: TimestampDefault, + tcpdumpFlag: "(default)", + }, + { + name: "none produces -t", + cliFlag: "none", + expectedEnum: TimestampNone, + tcpdumpFlag: "-t", + }, + { + name: "unformatted produces -tt", + cliFlag: "unformatted", + expectedEnum: TimestampUnformatted, + tcpdumpFlag: "-tt", + }, + { + name: "delta produces -ttt", + cliFlag: "delta", + expectedEnum: TimestampDelta, + tcpdumpFlag: "-ttt", + }, + { + name: "date produces -tttt", + cliFlag: "date", + expectedEnum: TimestampDate, + tcpdumpFlag: "-tttt", + }, + { + name: "delta-since-first produces -ttttt", + cliFlag: "delta-since-first", + expectedEnum: TimestampDeltaSinceFirst, + tcpdumpFlag: "-ttttt", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + format := TimestampFormat(tt.cliFlag) + if format != tt.expectedEnum { + t.Errorf("TimestampFormat(%q) = %q, want %q", tt.cliFlag, format, tt.expectedEnum) + } + if err := format.Validate(); err != nil { + t.Errorf("TimestampFormat(%q).Validate() error = %v", tt.cliFlag, err) + } + t.Logf("✓ --timestamp-format=%s → %s → tcpdump %s", tt.cliFlag, tt.expectedEnum, tt.tcpdumpFlag) + }) + } +} + +// TestEnumMapping_PrintData tests that the enum values correctly map to their intended usage +func TestEnumMapping_PrintData(t *testing.T) { + tests := []struct { + name string + cliFlag string + expectedEnum PrintDataFormat + tcpdumpFlag string + }{ + { + name: "default means no data printing", + cliFlag: "", + expectedEnum: PrintDataNone, + tcpdumpFlag: "(none)", + }, + { + name: "hex produces -x", + cliFlag: "hex", + expectedEnum: PrintDataHex, + tcpdumpFlag: "-x", + }, + { + name: "hex-with-link produces -xx", + cliFlag: "hex-with-link", + expectedEnum: PrintDataHexWithLink, + tcpdumpFlag: "-xx", + }, + { + name: "ascii produces -A", + cliFlag: "ascii", + expectedEnum: PrintDataASCII, + tcpdumpFlag: "-A", + }, + { + name: "ascii-with-link produces -AA", + cliFlag: "ascii-with-link", + expectedEnum: PrintDataASCIIWithLink, + tcpdumpFlag: "-AA", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + format := PrintDataFormat(tt.cliFlag) + if format != tt.expectedEnum { + t.Errorf("PrintDataFormat(%q) = %q, want %q", tt.cliFlag, format, tt.expectedEnum) + } + if err := format.Validate(); err != nil { + t.Errorf("PrintDataFormat(%q).Validate() error = %v", tt.cliFlag, err) + } + t.Logf("✓ --print-data=%s → %s → tcpdump %s", tt.cliFlag, tt.expectedEnum, tt.tcpdumpFlag) + }) + } +} diff --git a/crd/api/v1alpha1/capture_types.go b/crd/api/v1alpha1/capture_types.go index dfa23cf857..c16eaea0d7 100644 --- a/crd/api/v1alpha1/capture_types.go +++ b/crd/api/v1alpha1/capture_types.go @@ -67,10 +67,89 @@ type CaptureOption struct { MaxCaptureSize *int `json:"maxCaptureSize,omitempty"` // Interfaces specifies the network interfaces on which to capture packets. - // If specified, captures only on the listed interfaces. + // If specified, captures only on the listed interfaces (e.g., ["eth0", "eth1"]). // If empty, captures on all interfaces by default. + // Use this field to select specific interfaces, NOT the tcpdumpFilter field. // +optional Interfaces []string `json:"interfaces,omitempty"` + + // PcapFilter specifies a BPF filter expression for packet filtering (e.g., "tcp port 443", "host 10.0.0.1"). + // Only BPF expressions are allowed, no flags. See https://www.tcpdump.org/manpages/pcap-filter.7.html + // +optional + // +kubebuilder:validation:MaxLength=1024 + // +kubebuilder:validation:Pattern="^[^-]*$" + PcapFilter *string `json:"pcapFilter,omitempty"` + + // NoPromiscuous disables promiscuous mode for packet capture. + // When true, only packets destined for this host are captured (equivalent to tcpdump -p flag). + // When false or unset, captures all packets on the network segment (default behavior). + // +optional + NoPromiscuous *bool `json:"noPromiscuous,omitempty"` + + // PacketBuffered enables packet-buffered output mode (equivalent to tcpdump -U flag). + // When true, packets are written to output as soon as they're captured rather than being buffered. + // Useful for real-time monitoring but may impact performance. + // +optional + PacketBuffered *bool `json:"packetBuffered,omitempty"` + + // ImmediateMode enables immediate mode for packet capture (equivalent to tcpdump --immediate-mode). + // When true, packets are delivered to the application immediately rather than being buffered. + // This can reduce latency but may increase CPU usage. + // +optional + ImmediateMode *bool `json:"immediateMode,omitempty"` + + // NoResolveDNS disables DNS resolution for captured addresses (equivalent to tcpdump -n flag). + // When true, IP addresses are displayed numerically without resolving hostnames. + // This speeds up capture processing and avoids DNS lookup overhead. + // +optional + NoResolveDNS *bool `json:"noResolveDNS,omitempty"` + + // NoResolvePort disables port name resolution (equivalent to tcpdump -nn flag). + // When true, both IP addresses and port numbers are displayed numerically. + // This prevents service name lookups for port numbers. + // +optional + NoResolvePort *bool `json:"noResolvePort,omitempty"` + + // Verbosity controls the verbosity level of packet capture output. + // Valid values: "" (normal/default), "verbose" (tcpdump -v), "extra" (tcpdump -vv), "max" (tcpdump -vvv). + // Empty string means normal verbosity with no extra verbose flags. + // +optional + // +kubebuilder:validation:Enum="";verbose;extra;max + Verbosity *string `json:"verbosity,omitempty"` + + // PrintDataFormat controls how packet data is printed in the output. + // Valid values: "" (none), "hex" (tcpdump -x), "hex-with-link" (tcpdump -xx), "ascii" (tcpdump -A), "ascii-with-link" (tcpdump -AA). + // Empty string means no packet data printing. + // +optional + // +kubebuilder:validation:Enum="";hex;hex-with-link;ascii;ascii-with-link + PrintDataFormat *string `json:"printDataFormat,omitempty"` + + // PrintLinkHeader prints link-level (Ethernet) headers (equivalent to tcpdump -e flag). + // Shows MAC addresses and other link-layer information. + // +optional + PrintLinkHeader *bool `json:"printLinkHeader,omitempty"` + + // QuietOutput enables quiet/quick output mode (equivalent to tcpdump -q flag). + // Prints less protocol information for shorter output lines. + // +optional + QuietOutput *bool `json:"quietOutput,omitempty"` + + // AbsoluteSeq prints absolute TCP sequence numbers (equivalent to tcpdump -S flag). + // Shows actual sequence numbers instead of relative numbers. + // +optional + AbsoluteSeq *bool `json:"absoluteSeq,omitempty"` + + // TimestampFormat controls the timestamp format in packet capture output. + // Valid values: "" (default), "none" (tcpdump -t), "unformatted" (tcpdump -tt), "delta" (tcpdump -ttt), "date" (tcpdump -tttt), "delta-since-first" (tcpdump -ttttt). + // Empty string means default timestamp format. + // +optional + // +kubebuilder:validation:Enum="";none;unformatted;delta;date;delta-since-first + TimestampFormat *string `json:"timestampFormat,omitempty"` + + // DontVerifyChecksum disables TCP checksum verification (equivalent to tcpdump -K flag). + // Skips TCP checksum validation for captured packets. + // +optional + DontVerifyChecksum *bool `json:"dontVerifyChecksum,omitempty"` } // CaptureTarget indicates the target on which the network packets capture will be performed. @@ -106,8 +185,13 @@ type CaptureConfiguration struct { // +optional Filters *CaptureConfigurationFilters `json:"filters,omitempty"` - // TcpdumpFilter is a raw tcpdump filter string. + // TcpdumpFilter accepts BPF filter expressions only (no flags). + // + // DEPRECATED and will be removed: Currently functional but scheduled for removal. + // Use captureOption.pcapFilter for BPF expressions and captureOption boolean flags for tcpdump display options instead. // +optional + // +kubebuilder:validation:MaxLength=1024 + // +kubebuilder:validation:Pattern="^[^-]*$" TcpdumpFilter *string `json:"tcpdumpFilter,omitempty"` // IncludeMetadata represents whether or not networking metadata should be captured. diff --git a/crd/api/v1alpha1/zz_generated.deepcopy.go b/crd/api/v1alpha1/zz_generated.deepcopy.go index 3229a38b32..9ce7d26d4b 100644 --- a/crd/api/v1alpha1/zz_generated.deepcopy.go +++ b/crd/api/v1alpha1/zz_generated.deepcopy.go @@ -143,6 +143,71 @@ func (in *CaptureOption) DeepCopyInto(out *CaptureOption) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.PcapFilter != nil { + in, out := &in.PcapFilter, &out.PcapFilter + *out = new(string) + **out = **in + } + if in.NoPromiscuous != nil { + in, out := &in.NoPromiscuous, &out.NoPromiscuous + *out = new(bool) + **out = **in + } + if in.PacketBuffered != nil { + in, out := &in.PacketBuffered, &out.PacketBuffered + *out = new(bool) + **out = **in + } + if in.ImmediateMode != nil { + in, out := &in.ImmediateMode, &out.ImmediateMode + *out = new(bool) + **out = **in + } + if in.NoResolveDNS != nil { + in, out := &in.NoResolveDNS, &out.NoResolveDNS + *out = new(bool) + **out = **in + } + if in.NoResolvePort != nil { + in, out := &in.NoResolvePort, &out.NoResolvePort + *out = new(bool) + **out = **in + } + if in.Verbosity != nil { + in, out := &in.Verbosity, &out.Verbosity + *out = new(string) + **out = **in + } + if in.PrintDataFormat != nil { + in, out := &in.PrintDataFormat, &out.PrintDataFormat + *out = new(string) + **out = **in + } + if in.PrintLinkHeader != nil { + in, out := &in.PrintLinkHeader, &out.PrintLinkHeader + *out = new(bool) + **out = **in + } + if in.QuietOutput != nil { + in, out := &in.QuietOutput, &out.QuietOutput + *out = new(bool) + **out = **in + } + if in.AbsoluteSeq != nil { + in, out := &in.AbsoluteSeq, &out.AbsoluteSeq + *out = new(bool) + **out = **in + } + if in.TimestampFormat != nil { + in, out := &in.TimestampFormat, &out.TimestampFormat + *out = new(string) + **out = **in + } + if in.DontVerifyChecksum != nil { + in, out := &in.DontVerifyChecksum, &out.DontVerifyChecksum + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CaptureOption. diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml index 3eb3f66f9b..64c414b5dc 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.19.0 name: captures.retina.sh spec: group: retina.sh @@ -48,16 +48,33 @@ spec: captureOption: description: CaptureOption lists the options of the capture. properties: + absoluteSeq: + description: |- + AbsoluteSeq prints absolute TCP sequence numbers (equivalent to tcpdump -S flag). + Shows actual sequence numbers instead of relative numbers. + type: boolean + dontVerifyChecksum: + description: |- + DontVerifyChecksum disables TCP checksum verification (equivalent to tcpdump -K flag). + Skips TCP checksum validation for captured packets. + type: boolean duration: description: Duration indicates length of time that the capture should continue for. pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ type: string + immediateMode: + description: |- + ImmediateMode enables immediate mode for packet capture (equivalent to tcpdump --immediate-mode). + When true, packets are delivered to the application immediately rather than being buffered. + This can reduce latency but may increase CPU usage. + type: boolean interfaces: description: |- Interfaces specifies the network interfaces on which to capture packets. - If specified, captures only on the listed interfaces. + If specified, captures only on the listed interfaces (e.g., ["eth0", "eth1"]). If empty, captures on all interfaces by default. + Use this field to select specific interfaces, NOT the tcpdumpFilter field. items: type: string type: array @@ -66,10 +83,87 @@ spec: description: MaxCaptureSize limits the capture file to MB in size. type: integer + noPromiscuous: + description: |- + NoPromiscuous disables promiscuous mode for packet capture. + When true, only packets destined for this host are captured (equivalent to tcpdump -p flag). + When false or unset, captures all packets on the network segment (default behavior). + type: boolean + noResolveDNS: + description: |- + NoResolveDNS disables DNS resolution for captured addresses (equivalent to tcpdump -n flag). + When true, IP addresses are displayed numerically without resolving hostnames. + This speeds up capture processing and avoids DNS lookup overhead. + type: boolean + noResolvePort: + description: |- + NoResolvePort disables port name resolution (equivalent to tcpdump -nn flag). + When true, both IP addresses and port numbers are displayed numerically. + This prevents service name lookups for port numbers. + type: boolean + packetBuffered: + description: |- + PacketBuffered enables packet-buffered output mode (equivalent to tcpdump -U flag). + When true, packets are written to output as soon as they're captured rather than being buffered. + Useful for real-time monitoring but may impact performance. + type: boolean packetSize: description: PacketSize limits the each packet to bytes in size and packets longer than PacketSize will be truncated. type: integer + pcapFilter: + description: |- + PcapFilter specifies a BPF filter expression for packet filtering (e.g., "tcp port 443", "host 10.0.0.1"). + Only BPF expressions are allowed, no flags. See https://www.tcpdump.org/manpages/pcap-filter.7.html + maxLength: 1024 + pattern: ^[^-]*$ + type: string + printDataFormat: + description: |- + PrintDataFormat controls how packet data is printed in the output. + Valid values: "" (none), "hex" (tcpdump -x), "hex-with-link" (tcpdump -xx), "ascii" (tcpdump -A), "ascii-with-link" (tcpdump -AA). + Empty string means no packet data printing. + enum: + - "" + - hex + - hex-with-link + - ascii + - ascii-with-link + type: string + printLinkHeader: + description: |- + PrintLinkHeader prints link-level (Ethernet) headers (equivalent to tcpdump -e flag). + Shows MAC addresses and other link-layer information. + type: boolean + quietOutput: + description: |- + QuietOutput enables quiet/quick output mode (equivalent to tcpdump -q flag). + Prints less protocol information for shorter output lines. + type: boolean + timestampFormat: + description: |- + TimestampFormat controls the timestamp format in packet capture output. + Valid values: "" (default), "none" (tcpdump -t), "unformatted" (tcpdump -tt), "delta" (tcpdump -ttt), "date" (tcpdump -tttt), "delta-since-first" (tcpdump -ttttt). + Empty string means default timestamp format. + enum: + - "" + - none + - unformatted + - delta + - date + - delta-since-first + type: string + verbosity: + description: |- + Verbosity controls the verbosity level of packet capture output. + Valid values: "" (normal/default), "verbose" (tcpdump -v), "extra" (tcpdump -vv), "max" (tcpdump -vvv). + Empty string means normal verbosity with no extra verbose flags. + enum: + - "" + - verbose + - extra + - max + type: string type: object captureTarget: description: CaptureTarget indicates the target on which the network @@ -263,7 +357,13 @@ spec: - Network statistics information type: boolean tcpdumpFilter: - description: TcpdumpFilter is a raw tcpdump filter string. + description: |- + TcpdumpFilter accepts BPF filter expressions only (no flags). + + DEPRECATED and will be removed: Currently functional but scheduled for removal. + Use captureOption.pcapFilter for BPF expressions and captureOption boolean flags for tcpdump display options instead. + maxLength: 1024 + pattern: ^[^-]*$ type: string required: - captureTarget diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml index 123fe4c108..1179c0092a 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_metricsconfigurations.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.19.0 name: metricsconfigurations.retina.sh spec: group: retina.sh diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml index f09c04ad0f..f091618a15 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_retinaendpoints.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.19.0 name: retinaendpoints.retina.sh spec: group: retina.sh diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml index d1850bfe44..1f6bce86b6 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_tracesconfigurations.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.19.0 name: tracesconfigurations.retina.sh spec: group: retina.sh diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index 6d07e625fa..ed761631ab 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -85,7 +85,22 @@ The network traffic will be uploaded to the specified output location. | `s3-region` | string | "" | Region where the S3 compatible bucket is located. | | | `s3-secret-access-key`| string | "" | S3 access secret key to upload capture files. | | | `interfaces` | string | "" | Comma-separated list of network interfaces to capture on (e.g., "eth0,eth1"). By default, captures are performed on all network interfaces. | | -| `tcpdump-filter` | string | "" | Raw tcpdump flags. Available tcpdump filters can be found in the [TCPDUMP MAN PAGE](https://www.tcpdump.org/manpages/tcpdump.1.html). This overrides interface selection options when specified. | Only works on Linux. Includes only tcpdump flags, for boolean expressions, please use include/exclude filters. | +| `pcap-filter` | string | "" | BPF filter expression for packet filtering (e.g., "host 10.0.0.1", "tcp port 443"). See [PCAP-FILTER](https://www.tcpdump.org/manpages/pcap-filter.7.html) for BPF syntax. Does NOT accept flags (arguments starting with '-'). | | +| `tcpdump-filter` | string | "" | **DEPRECATED and will be removed.** Use `--pcap-filter` instead. BPF filter expression for packet filtering. Does NOT accept flags (arguments starting with '-'). | | +| `no-promiscuous` | bool | false | Disable promiscuous mode (equivalent to tcpdump -p flag). | | +| `packet-buffered` | bool | false | Enable packet-buffered output (equivalent to tcpdump -U flag). | | +| `immediate-mode` | bool | false | Enable immediate mode for packet capture (equivalent to tcpdump --immediate-mode). | | +| `no-resolve-dns` | bool | false | Don't resolve hostnames (equivalent to tcpdump -n flag). | | +| `no-resolve-port` | bool | false | Don't resolve hostnames or port names (equivalent to tcpdump -nn flag). | | +| `verbosity` | string | "" | Verbosity level: `verbose` (tcpdump -v), `extra` (tcpdump -vv), `max` (tcpdump -vvv). Mutually exclusive. | | +| `timestamp-format` | string | "" | Timestamp format: `none` (-t), `unformatted` (-tt), `delta` (-ttt), `date` (-tttt), `delta-since-first` (-ttttt). Mutually exclusive. | | +| `print-data` | string | "" | Print packet data: `hex` (-x), `hex-with-link` (-xx), `ascii` (-A), `ascii-with-link` (-AA). Mutually exclusive. | | +| `print-link-header` | bool | false | Print link-level headers (equivalent to tcpdump -e flag). | | +| `quiet-output` | bool | false | Quick/quiet output mode (equivalent to tcpdump -q flag). | | +| `absolute-seq` | bool | false | Print absolute TCP sequence numbers (equivalent to tcpdump -S flag). | | +| `dont-verify-checksum`| bool | false | Don't verify TCP checksums (equivalent to tcpdump -K flag). | | + +> **Note on Mutually Exclusive Flags**: The `verbosity`, `timestamp-format`, and `print-data` flags are mutually exclusive within their respective groups. You can only set one value per flag. For example, you cannot use both `--verbosity=verbose` and `--verbosity=max` simultaneously. The CLI enforces this by using enum-based flags instead of individual boolean flags. #### Examples @@ -213,12 +228,47 @@ kubectl retina capture create \ --exclude-filter="10.224.0.26:80,10.224.0.34:8080" ``` -Tcpdump Filters +BPF Packet Filters ```sh kubectl retina capture create \ - --name example-tcpdump-filters \ - --tcpdump-filter="udp port 53" + --name example-pcap-filters \ + --pcap-filter="udp port 53" +``` + +Capture with Display Options + +```sh +kubectl retina capture create \ + --name example-with-display-options \ + --pcap-filter="tcp port 443" \ + --no-resolve-dns \ + --verbosity=verbose \ + --print-data=hex +``` + +This example: + +- Captures only HTTPS traffic (tcp port 443) +- Doesn't resolve hostnames (--no-resolve-dns, equivalent to tcpdump -n) +- Shows verbose output (--verbosity=verbose, equivalent to tcpdump -v) +- Displays packet data in hex (--print-data=hex, equivalent to tcpdump -x) + +Additional display option examples: + +```sh +# Don't resolve names or ports, capture HTTP traffic +kubectl retina capture create \ + --name example-http \ + --pcap-filter="tcp port 80" \ + --no-resolve-port + +# Show timestamps with date and link-level headers for ICMP +kubectl retina capture create \ + --name example-icmp \ + --pcap-filter="icmp" \ + --timestamp-format=date \ + --print-link-header ``` ### Capture Delete diff --git a/docs/05-Concepts/CRDs/Capture.md b/docs/05-Concepts/CRDs/Capture.md index 7c6d1af3ee..41d371583e 100644 --- a/docs/05-Concepts/CRDs/Capture.md +++ b/docs/05-Concepts/CRDs/Capture.md @@ -23,11 +23,29 @@ The `Capture` CRD is defined with the following specifications: ### Fields - **spec.captureConfiguration:** Specifies the configuration for capturing network packets. It includes the following properties: - - `captureOption`: Lists options for the capture, such as duration, maximum capture size, and packet size. + - `captureOption`: Lists options for the capture, such as: + - `duration`: Capture duration + - `maxCaptureSize`: Maximum capture file size in MB + - `packetSize`: Maximum packet size to capture + - `interfaces`: Array of network interface names to capture from (e.g., `["eth0", "eth1"]`). If empty, captures from all interfaces. + - `pcapFilter`: BPF filter expression for packet filtering (e.g., `"host 10.0.0.1"`, `"tcp port 443"`). Does NOT accept flags. + - Boolean flags for tcpdump capture behavior and display options: + - `noPromiscuous`: Disable promiscuous mode (tcpdump -p) + - `packetBuffered`: Enable packet-buffered output (tcpdump -U) + - `immediateMode`: Enable immediate mode (tcpdump --immediate-mode) + - `noResolveDNS`: Don't resolve hostnames (tcpdump -n) + - `noResolvePort`: Don't resolve hostnames or port names (tcpdump -nn) + - `verbose`, `extraVerbose`, `maxVerbose`: Verbose output levels (tcpdump -v, -vv, -vvv). **Mutually exclusive** - set only one. + - `printDataHex`, `printDataHexLink`, `printDataASCII`, `printDataASCIILink`: Print packet data in hex (tcpdump -x, -xx) or ASCII (tcpdump -A, -AA). **Mutually exclusive** - set only one print data format. + - `printLinkHeader`: Print link-level headers (tcpdump -e) + - `quietOutput`: Quick/quiet output (tcpdump -q) + - `absoluteSeq`: Print absolute TCP sequence numbers (tcpdump -S) + - `noTimestamp`, `unformattedTimestamp`, `deltaTimestamp`, `dateTimestamp`, `deltaSinceFirst`: Timestamp options (tcpdump -t, -tt, -ttt, -tttt, -ttttt). **Mutually exclusive** - set only one. + - `dontVerifyChecksum`: Don't verify TCP checksums (tcpdump -K) - `captureTarget`: Defines the target on which the network packets will be captured. It includes namespace, node, and pod selectors, as well as specific pod names. - `filters`: Specifies filters for including or excluding network packets based on IP or port. - `includeMetadata`: Indicates whether networking metadata should be captured. - - `tcpdumpFilter`: Allows specifying a raw tcpdump filter string. + - `tcpdumpFilter`: **DEPRECATED and will be removed.** Currently accepts BPF filter expressions only (no flags). Migrate to `captureOption.pcapFilter` for BPF expressions and `captureOption` boolean flags for display/output options (e.g., `noResolveDNS`, `packetBuffered`, `verbosity`). - **spec.outputConfiguration:** Indicates where the captured data will be stored. It includes the following properties: - `blobUpload`: Specifies a secret containing the blob SAS URL for storing the capture data. @@ -76,6 +94,138 @@ data: s3-secret-access-key: ``` +### Advanced Filtering + +#### Capturing on Specific Network Interfaces + +To capture packets only on specific network interfaces, use the `captureOption.interfaces` field: + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: capture-specific-interfaces +spec: + captureConfiguration: + captureOption: + duration: "1m" + interfaces: ["eth0", "eth1"] # Capture only on these interfaces + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/hostname: node-1 + outputConfiguration: + hostPath: /tmp/captures +``` + +#### Using BPF Filters with Display Options + +The `captureOption.pcapFilter` field accepts BPF (Berkeley Packet Filter) expressions for packet filtering. Use boolean flags in `captureOption` for display and output formatting. + +##### BPF Filters Only + +To apply packet filtering using BPF syntax: + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: capture-with-bpf-filter +spec: + captureConfiguration: + captureOption: + duration: "1m" + pcapFilter: "tcp and (port 443 or port 80)" # Only capture HTTP/HTTPS traffic + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/hostname: node-1 + outputConfiguration: + hostPath: /tmp/captures +``` + +**Valid BPF filter examples:** + +- `"host 10.0.0.1"` - Capture packets to/from specific host +- `"tcp port 443"` - Capture HTTPS traffic +- `"net 192.168.0.0/16 and not port 22"` - Capture subnet traffic except SSH +- `"tcp and (port 80 or port 443)"` - Capture HTTP and HTTPS traffic + +##### Using Display Options with BPF Filters + +Combine BPF filters with display option boolean flags: + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: capture-with-display-options +spec: + captureConfiguration: + captureOption: + duration: "1m" + pcapFilter: "tcp port 443" + noResolveDNS: true # Don't resolve hostnames (tcpdump -n) + verbose: true # Verbose output (tcpdump -v) + printDataHex: true # Show hex data (tcpdump -x) + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/hostname: node-1 + outputConfiguration: + hostPath: /tmp/captures +``` + +**Examples with different display options:** + +```yaml +# Don't resolve names or ports, very verbose, capture HTTP +captureOption: + pcapFilter: "tcp port 80" + noResolvePort: true # tcpdump -nn + extraVerbose: true # tcpdump -vv +``` + +```yaml +# Show hex data with timestamps, capture ICMP +captureOption: + pcapFilter: "icmp" + printDataHex: true # tcpdump -x + dateTimestamp: true # tcpdump -tttt +``` + +**Available display option and boolean flags:** + +- `noResolveDNS`, `noResolvePort`: Don't resolve hostnames/port names (tcpdump -n, -nn) +- **Verbosity** (mutually exclusive - choose one): + - `verbose`: Verbose output (tcpdump -v) + - `extraVerbose`: Extra verbose output (tcpdump -vv) + - `maxVerbose`: Maximum verbose output (tcpdump -vvv) +- **Print data format** (mutually exclusive - choose one): + - `printDataHex`: Show packet data in hex (tcpdump -x) + - `printDataHexLink`: Show packet data in hex with link-level headers (tcpdump -xx) + - `printDataASCII`: Show packet data in ASCII (tcpdump -A) + - `printDataASCIILink`: Show packet data in ASCII with link-level headers (tcpdump -AA) +- **Timestamp format** (mutually exclusive - choose one): + - `noTimestamp`: Don't print timestamps (tcpdump -t) + - `unformattedTimestamp`: Print timestamps as Unix epoch (tcpdump -tt) + - `deltaTimestamp`: Print time delta between packets (tcpdump -ttt) + - `dateTimestamp`: Print timestamps with date (tcpdump -tttt) + - `deltaSinceFirst`: Print time delta since first packet (tcpdump -ttttt) +- Other options: + - `printLinkHeader`: Print link-level headers (tcpdump -e) + - `quietOutput`: Quick/quiet output (tcpdump -q) + - `absoluteSeq`: Print absolute TCP sequence numbers (tcpdump -S) + - `dontVerifyChecksum`: Don't verify TCP checksums (tcpdump -K) + +> **CLI Users**: When using the `kubectl retina capture create` command, use the enum-based flags (`--verbosity`, `--timestamp-format`, `--print-data`) instead of setting these boolean fields directly. See the [CLI documentation](../../04-Captures/02-cli.md) for details. + +**Capture behavior options:** + +- `noPromiscuous`: Disable promiscuous mode (tcpdump -p) +- `packetBuffered`: Enable packet-buffered output (tcpdump -U) +- `immediateMode`: Enable immediate mode (tcpdump --immediate-mode) + ### Capture Lifecycle Once a Capture is created, the capture controller inside retina-operator is responsible for managing the lifecycle of the Capture. diff --git a/pkg/capture/constants/job_env.go b/pkg/capture/constants/job_env.go index 724a0fe78b..400e4646ca 100644 --- a/pkg/capture/constants/job_env.go +++ b/pkg/capture/constants/job_env.go @@ -32,6 +32,8 @@ const ( TcpdumpFilterEnvKey string = "TCPDUMP_FILTER" TcpdumpRawFilterEnvKey string = "TCPDUMP_RAW_FILTER" + PcapFilterEnvKey string = "PCAP_FILTER" + TcpdumpFlagsEnvKey string = "TCPDUMP_FLAGS" NetshFilterEnvKey string = "NETSH_FILTER" // Interface selection environment variables diff --git a/pkg/capture/crd_to_job.go b/pkg/capture/crd_to_job.go index 056e2d7155..86d2a8922a 100644 --- a/pkg/capture/crd_to_job.go +++ b/pkg/capture/crd_to_job.go @@ -40,6 +40,22 @@ var ( errPodNamesIncompat = errors.New("PodNames is not compatible with NamespaceSelector or PodSelector, please use one or the other") ) +// tcpdumpFlagMapping defines the mapping between CaptureOption boolean fields and their corresponding tcpdump flags. +var tcpdumpFlagMappings = []struct { + getBool func(*retinav1alpha1.CaptureOption) *bool + flag string +}{ + {func(o *retinav1alpha1.CaptureOption) *bool { return o.NoPromiscuous }, "-p"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.PacketBuffered }, "-U"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.ImmediateMode }, "--immediate-mode"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.NoResolveDNS }, "-n"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.NoResolvePort }, "-nn"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.PrintLinkHeader }, "-e"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.QuietOutput }, "-q"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.AbsoluteSeq }, "-S"}, + {func(o *retinav1alpha1.CaptureOption) *bool { return o.DontVerifyChecksum }, "-K"}, +} + // CaptureTarget indicates on which the network capture will be performed on a given node. type CaptureTarget struct { // PodIpAddresses indicates the capture is performed on the Pods per their IP addresses. @@ -1055,10 +1071,67 @@ func (translator *CaptureToPodTranslator) obtainCaptureJobPodEnv(capture retinav jobPodEnv[captureConstants.PacketSizeEnvKey] = strconv.Itoa(*capture.Spec.CaptureConfiguration.CaptureOption.PacketSize) } + if capture.Spec.CaptureConfiguration.CaptureOption.PcapFilter != nil { + jobPodEnv[captureConstants.PcapFilterEnvKey] = *capture.Spec.CaptureConfiguration.CaptureOption.PcapFilter + } + if capture.Spec.CaptureConfiguration.TcpdumpFilter != nil { jobPodEnv[captureConstants.TcpdumpRawFilterEnvKey] = *capture.Spec.CaptureConfiguration.TcpdumpFilter } + // Build tcpdump flags from CaptureOption boolean fields using the mapping table + var tcpdumpFlags []string + opt := &capture.Spec.CaptureConfiguration.CaptureOption + for _, mapping := range tcpdumpFlagMappings { + if boolVal := mapping.getBool(opt); boolVal != nil && *boolVal { + tcpdumpFlags = append(tcpdumpFlags, mapping.flag) + } + } + + // Handle enum fields for verbosity, print data format, and timestamp format + if opt.Verbosity != nil && *opt.Verbosity != "" { + switch *opt.Verbosity { + case "verbose": + tcpdumpFlags = append(tcpdumpFlags, "-v") + case "extra": + tcpdumpFlags = append(tcpdumpFlags, "-vv") + case "max": + tcpdumpFlags = append(tcpdumpFlags, "-vvv") + } + } + + if opt.PrintDataFormat != nil && *opt.PrintDataFormat != "" { + switch *opt.PrintDataFormat { + case "hex": + tcpdumpFlags = append(tcpdumpFlags, "-x") + case "hex-with-link": + tcpdumpFlags = append(tcpdumpFlags, "-xx") + case "ascii": + tcpdumpFlags = append(tcpdumpFlags, "-A") + case "ascii-with-link": + tcpdumpFlags = append(tcpdumpFlags, "-AA") + } + } + + if opt.TimestampFormat != nil && *opt.TimestampFormat != "" { + switch *opt.TimestampFormat { + case "none": + tcpdumpFlags = append(tcpdumpFlags, "-t") + case "unformatted": + tcpdumpFlags = append(tcpdumpFlags, "-tt") + case "delta": + tcpdumpFlags = append(tcpdumpFlags, "-ttt") + case "date": + tcpdumpFlags = append(tcpdumpFlags, "-tttt") + case "delta-since-first": + tcpdumpFlags = append(tcpdumpFlags, "-ttttt") + } + } + + if len(tcpdumpFlags) > 0 { + jobPodEnv[captureConstants.TcpdumpFlagsEnvKey] = strings.Join(tcpdumpFlags, " ") + } + if len(capture.Name) != 0 { jobPodEnv[captureConstants.CaptureNameEnvKey] = capture.Name } diff --git a/pkg/capture/crd_to_job_test.go b/pkg/capture/crd_to_job_test.go index c9349df8ad..9291590db8 100644 --- a/pkg/capture/crd_to_job_test.go +++ b/pkg/capture/crd_to_job_test.go @@ -582,6 +582,113 @@ func Test_CaptureToPodTranslator_ObtainCaptureJobPodEnv(t *testing.T) { captureConstants.PacketSizeEnvKey: strconv.Itoa(packetSize), }, }, + { + name: "pcapFilter", + capture: retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + PersistentVolumeClaim: pointerUtil.String("capture-pvc"), + }, + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureOption: retinav1alpha1.CaptureOption{ + PcapFilter: pointerUtil.String("tcp port 80"), + }, + }, + }, + }, + wantJobEnv: map[string]string{ + string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim): "capture-pvc", + captureConstants.IncludeMetadataEnvKey: "false", + captureConstants.PcapFilterEnvKey: "tcp port 80", + }, + }, + { + name: "deprecated tcpdumpFilter", + capture: retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + PersistentVolumeClaim: pointerUtil.String("capture-pvc"), + }, + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + TcpdumpFilter: pointerUtil.String("udp port 53"), + }, + }, + }, + wantJobEnv: map[string]string{ + string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim): "capture-pvc", + captureConstants.IncludeMetadataEnvKey: "false", + captureConstants.TcpdumpRawFilterEnvKey: "udp port 53", + }, + }, + { + name: "tcpdump boolean flags", + capture: retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + PersistentVolumeClaim: pointerUtil.String("capture-pvc"), + }, + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureOption: retinav1alpha1.CaptureOption{ + NoPromiscuous: pointerUtil.Bool(true), + Verbosity: pointerUtil.String("verbose"), + }, + }, + }, + }, + wantJobEnv: map[string]string{ + string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim): "capture-pvc", + captureConstants.IncludeMetadataEnvKey: "false", + captureConstants.TcpdumpFlagsEnvKey: "-p -v", + }, + }, + { + name: "multiple tcpdump boolean flags", + capture: retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + PersistentVolumeClaim: pointerUtil.String("capture-pvc"), + }, + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureOption: retinav1alpha1.CaptureOption{ + NoPromiscuous: pointerUtil.Bool(true), + NoResolveDNS: pointerUtil.Bool(true), + Verbosity: pointerUtil.String("verbose"), + PrintDataFormat: pointerUtil.String("hex"), + AbsoluteSeq: pointerUtil.Bool(true), + TimestampFormat: pointerUtil.String("none"), + }, + }, + }, + }, + wantJobEnv: map[string]string{ + string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim): "capture-pvc", + captureConstants.IncludeMetadataEnvKey: "false", + captureConstants.TcpdumpFlagsEnvKey: "-p -n -S -v -x -t", + }, + }, + { + name: "pcapFilter and boolean flags combined", + capture: retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + PersistentVolumeClaim: pointerUtil.String("capture-pvc"), + }, + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureOption: retinav1alpha1.CaptureOption{ + PcapFilter: pointerUtil.String("tcp port 443"), + NoPromiscuous: pointerUtil.Bool(true), + Verbosity: pointerUtil.String("verbose"), + }, + }, + }, + }, + wantJobEnv: map[string]string{ + string(captureConstants.CaptureOutputLocationEnvKeyPersistentVolumeClaim): "capture-pvc", + captureConstants.IncludeMetadataEnvKey: "false", + captureConstants.PcapFilterEnvKey: "tcp port 443", + captureConstants.TcpdumpFlagsEnvKey: "-p -v", + }, + }, } for _, tt := range cases { @@ -916,7 +1023,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { pvc := "capture-pvc" backoffLimit := int32(0) rootUser := int64(0) - tcpdumpFilter := "-i eth0" + tcpdumpFilter := "tcp port 443" captureFolderHostPathType := corev1.HostPathDirectoryOrCreate commonJob := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ @@ -1473,7 +1580,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, - {Name: captureConstants.TcpdumpRawFilterEnvKey, Value: "-i eth0"}, + {Name: captureConstants.TcpdumpRawFilterEnvKey, Value: "tcp port 443"}, {Name: captureConstants.TcpdumpFilterEnvKey, Value: "(host 10.225.0.4)"}, { Name: telemetry.EnvPodName, @@ -1798,7 +1905,7 @@ func Test_CaptureToPodTranslator_TranslateCaptureToJobs(t *testing.T) { {Name: captureConstants.CaptureStartTimestampEnvKey, Value: file.TimeToString(timestamp)}, {Name: captureConstants.IncludeMetadataEnvKey, Value: "false"}, {Name: captureConstants.NodeHostNameEnvKey, Value: "node1"}, - {Name: captureConstants.TcpdumpRawFilterEnvKey, Value: "-i eth0"}, + {Name: captureConstants.TcpdumpRawFilterEnvKey, Value: "tcp port 443"}, {Name: captureConstants.NetshFilterEnvKey, Value: "IPv4.Address=(10.225.0.4)"}, { Name: telemetry.EnvPodName, diff --git a/pkg/capture/provider/network_capture_test.go b/pkg/capture/provider/network_capture_test.go index b64d1364e0..b897bd9584 100644 --- a/pkg/capture/provider/network_capture_test.go +++ b/pkg/capture/provider/network_capture_test.go @@ -6,8 +6,11 @@ package provider import ( + "context" + "errors" "os" "os/exec" + "slices" "strings" "testing" @@ -18,10 +21,11 @@ import ( const ( testCaptureFilePath = "/tmp/test.pcap" + testCaptureName = "test-capture" + testNodeHostName = "test-node" interfaceEth0 = "eth0" interfaceEth1 = "eth1" interfaceAny = "any" - interfaceLo = "lo" ) func TestSetupAndCleanup(t *testing.T) { @@ -76,32 +80,58 @@ func hasInterface(cmd *exec.Cmd, expectedInterface string) bool { // Helper function to reset environment variables func resetEnvVars() { os.Unsetenv(captureConstants.TcpdumpRawFilterEnvKey) + os.Unsetenv(captureConstants.PcapFilterEnvKey) os.Unsetenv(captureConstants.PacketSizeEnvKey) os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) + os.Unsetenv(captureConstants.TcpdumpFlagsEnvKey) } -func TestTcpdumpDefaultBehavior(t *testing.T) { - resetEnvVars() +// Helper function to check if tcpdump is available on the system +func requireTcpdump(t *testing.T) { + t.Helper() + if _, err := exec.LookPath("tcpdump"); err != nil { + t.Skipf("tcpdump not available on system: %v", err) + } +} - cmd := constructTcpdumpCommand(testCaptureFilePath) +// TestTcpdumpEmptyFilter verifies that empty filter falls back to default interface +// and that no unexpected or malicious arguments are injected. +func TestTcpdumpEmptyFilter(t *testing.T) { + resetEnvVars() + cmd := constructTcpdumpCommand(testCaptureFilePath, "") + // Should fall back to "-i any" if !hasInterface(cmd, interfaceAny) { - t.Errorf("Expected tcpdump command to include '-i any', but got args: %v", cmd.Args) + t.Errorf("Expected fallback to '-i any' with empty filter, but got args: %v", cmd.Args) + } + + // Verify only expected args are present and no malicious content + for _, arg := range cmd.Args { + if arg != "tcpdump" && arg != "-w" && arg != testCaptureFilePath && + arg != "--relinquish-privileges=root" && arg != "-i" && arg != interfaceAny { + t.Errorf("Unexpected argument '%s' found in empty filter command: %v", arg, cmd.Args) + } + // Check for malicious content + if strings.Contains(arg, "/etc/passwd") || strings.Contains(arg, "evil") || + strings.Contains(arg, "rm -rf") || strings.HasPrefix(arg, "-z") { + t.Errorf("Malicious content should not be present in command args: %v", cmd.Args) + } } } -func TestTcpdumpRawFilterOverride(t *testing.T) { +func TestTcpdumpWithBPFFilter(t *testing.T) { resetEnvVars() - os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, "-i "+interfaceEth0) - defer os.Unsetenv(captureConstants.TcpdumpRawFilterEnvKey) + // Test that a valid BPF filter is properly added to the tcpdump command + // Note: Filter validation (e.g., rejecting '-' prefix) happens in CaptureNetworkPacket - cmd := constructTcpdumpCommand(testCaptureFilePath) + bpfFilter := "tcp port 80" - if !hasInterface(cmd, interfaceEth0) { - t.Errorf("Expected tcpdump command to include '-i %s' from raw filter, but got args: %v", interfaceEth0, cmd.Args) - } - if hasInterface(cmd, interfaceAny) { - t.Errorf("Expected tcpdump command not to include '-i any' when raw filter is set, but got args: %v", cmd.Args) + cmd := constructTcpdumpCommand(testCaptureFilePath, bpfFilter) + + // Should have the BPF filter as an argument + found := slices.Contains(cmd.Args, bpfFilter) + if !found { + t.Errorf("Expected BPF filter '%s' in args, but got: %v", bpfFilter, cmd.Args) } } @@ -110,7 +140,7 @@ func TestTcpdumpSpecificInterfaces(t *testing.T) { os.Setenv(captureConstants.CaptureInterfacesEnvKey, interfaceEth0+","+interfaceEth1) defer os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) - cmd := constructTcpdumpCommand(testCaptureFilePath) + cmd := constructTcpdumpCommand(testCaptureFilePath, "") if !hasInterface(cmd, interfaceEth0) { t.Errorf("Expected tcpdump command to include '-i %s', but got args: %v", interfaceEth0, cmd.Args) @@ -123,42 +153,559 @@ func TestTcpdumpSpecificInterfaces(t *testing.T) { } } -func TestTcpdumpRawFilterPriority(t *testing.T) { +func TestTcpdumpBPFFilterWithSpecificInterfaces(t *testing.T) { resetEnvVars() - os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, "-i "+interfaceLo) + // Verify that BPF filter and specific interface selection work together + // Both should be present in the command (they are independent features) + bpfFilter := "tcp port 443" os.Setenv(captureConstants.CaptureInterfacesEnvKey, interfaceEth0+","+interfaceEth1) - defer os.Unsetenv(captureConstants.TcpdumpRawFilterEnvKey) defer os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) - cmd := constructTcpdumpCommand(testCaptureFilePath) + cmd := constructTcpdumpCommand(testCaptureFilePath, bpfFilter) + + // The BPF filter should be present + found := slices.Contains(cmd.Args, bpfFilter) + if !found { + t.Errorf("Expected BPF filter '%s' in command, but got args: %v", bpfFilter, cmd.Args) + } + + // Interfaces should still be present (BPF filter doesn't override interface selection) + if !hasInterface(cmd, interfaceEth0) || !hasInterface(cmd, interfaceEth1) { + t.Errorf("Expected both interfaces to be present with BPF filter, but got args: %v", cmd.Args) + } +} + +func TestTcpdumpCommandConstruction(t *testing.T) { + // Default behavior tests + t.Run("EmptyFilter", TestTcpdumpEmptyFilter) + + // Interface selection tests + t.Run("SpecificInterfaceSelection", TestTcpdumpSpecificInterfaces) + t.Run("InterfaceListWithEmptyEntries", TestTcpdumpInterfaceListWithEmptyEntries) + + // BPF filter tests + t.Run("WithBPFFilter", TestTcpdumpWithBPFFilter) + t.Run("BPFFilterWithSpecificInterfaces", TestTcpdumpBPFFilterWithSpecificInterfaces) + t.Run("BPFFilterWithComplexExpression", TestTcpdumpBPFFilterComplexExpression) + t.Run("BPFFilterWithTcpFlags", TestTcpdumpBPFFilterWithTcpFlags) + + // Option tests + t.Run("PacketSizeOption", TestTcpdumpPacketSizeOption) +} + +// TestTcpdumpBPFFilterComplexExpression validates that complex BPF filter expressions +// with multiple keywords and operators are passed as a single argument, not split on spaces. +// This is critical for security - splitting would allow flag injection attacks. +func TestTcpdumpBPFFilterComplexExpression(t *testing.T) { + resetEnvVars() + // Test a complex BPF filter that should remain as one argument + bpfFilter := "tcp and (port 80 or port 443) and host 10.0.0.1" + + cmd := constructTcpdumpCommand(testCaptureFilePath, bpfFilter) + + // The entire filter must appear as a single argument + found := slices.Contains(cmd.Args, bpfFilter) + if !found { + t.Errorf("Expected entire BPF filter '%s' as single argument, but got args: %v", bpfFilter, cmd.Args) + } + + // Verify individual keywords are NOT separate arguments (which would indicate splitting) + splitIndicators := []string{"tcp", "and", "port", "80", "or", "443", "host", "10.0.0.1"} + for _, indicator := range splitIndicators { + for _, arg := range cmd.Args { + if arg == indicator { + t.Errorf("BPF filter was incorrectly split: found '%s' as separate arg in: %v", indicator, cmd.Args) + } + } + } +} + +// TestTcpdumpBPFFilterWithTcpFlags verifies that BPF filters using TCP flag syntax +// with special characters like brackets, pipes, and ampersands are passed correctly. +// Example: tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn +func TestTcpdumpBPFFilterWithTcpFlags(t *testing.T) { + resetEnvVars() + // Test a BPF filter with TCP flags syntax and special characters + bpfFilter := "tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn" + + cmd := constructTcpdumpCommand(testCaptureFilePath, bpfFilter) - if !hasInterface(cmd, interfaceLo) { - t.Errorf("Expected tcpdump command to include '-i %s' from raw filter, but got args: %v", interfaceLo, cmd.Args) + // Positive check: The entire filter must appear as a single argument + found := slices.Contains(cmd.Args, bpfFilter) + if !found { + t.Errorf("Expected entire BPF filter '%s' as single argument, but got args: %v", bpfFilter, cmd.Args) } - if hasInterface(cmd, interfaceEth0) || hasInterface(cmd, interfaceEth1) { - t.Errorf("Expected tcpdump command not to include specific interfaces when raw filter is set, but got args: %v", cmd.Args) + + // Negative check: Verify the filter is not split on spaces (which would indicate incorrect handling) + // These are the pieces that would appear if the filter were split on spaces + splitIndicators := []string{"tcp[tcpflags]", "&", "(tcp-syn|tcp-ack)", "==", "tcp-syn"} + for _, indicator := range splitIndicators { + for _, arg := range cmd.Args { + if arg == indicator { + t.Errorf("BPF filter was incorrectly split: found '%s' as separate arg in: %v", indicator, cmd.Args) + } + } } } -func TestTcpdumpInterfaceOverrideDefault(t *testing.T) { +// TestTcpdumpInterfaceListWithEmptyEntries verifies handling of interface lists with empty values +func TestTcpdumpInterfaceListWithEmptyEntries(t *testing.T) { resetEnvVars() - os.Setenv(captureConstants.CaptureInterfacesEnvKey, interfaceEth0) + // Interface list with empty entries and extra spaces + os.Setenv(captureConstants.CaptureInterfacesEnvKey, "eth0, ,eth1,,eth2, ") defer os.Unsetenv(captureConstants.CaptureInterfacesEnvKey) - cmd := constructTcpdumpCommand(testCaptureFilePath) + cmd := constructTcpdumpCommand(testCaptureFilePath, "") + // Should only include non-empty interfaces if !hasInterface(cmd, interfaceEth0) { - t.Errorf("Expected tcpdump command to include '-i %s' from specific interfaces, but got args: %v", interfaceEth0, cmd.Args) + t.Errorf("Expected '-i eth0', but got args: %v", cmd.Args) } - if hasInterface(cmd, interfaceAny) { - t.Errorf("Expected tcpdump command not to include '-i any' when specific interfaces are set, but got args: %v", cmd.Args) + if !hasInterface(cmd, interfaceEth1) { + t.Errorf("Expected '-i eth1', but got args: %v", cmd.Args) + } + // eth2 should be present + if !hasInterface(cmd, "eth2") { + t.Errorf("Expected '-i eth2', but got args: %v", cmd.Args) } } -func TestTcpdumpCommandConstruction(t *testing.T) { - t.Run("DefaultBehaviorIncludesAnyInterface", TestTcpdumpDefaultBehavior) - t.Run("RawFilterOverridesDefault", TestTcpdumpRawFilterOverride) - t.Run("SpecificInterfaceSelection", TestTcpdumpSpecificInterfaces) - t.Run("RawFilterOverridesSpecificInterfaces", TestTcpdumpRawFilterPriority) - t.Run("SpecificInterfacesOverrideDefault", TestTcpdumpInterfaceOverrideDefault) +// TestTcpdumpPacketSizeOption verifies that packet size option is correctly added +func TestTcpdumpPacketSizeOption(t *testing.T) { + resetEnvVars() + os.Setenv(captureConstants.PacketSizeEnvKey, "1500") + defer os.Unsetenv(captureConstants.PacketSizeEnvKey) + + cmd := constructTcpdumpCommand(testCaptureFilePath, "") + + // Should include -s 1500 + foundS := false + foundSize := false + for i, arg := range cmd.Args { + if arg == "-s" { + foundS = true + if i+1 < len(cmd.Args) && cmd.Args[i+1] == "1500" { + foundSize = true + } + } + } + if !foundS || !foundSize { + t.Errorf("Expected '-s 1500' in tcpdump args, but got: %v", cmd.Args) + } +} + +// TestTcpdumpBPFFilterOnly verifies command construction with BPF filter (no user flags) +func TestTcpdumpBPFFilterOnly(t *testing.T) { + resetEnvVars() + bpfFilter := "tcp port 80" + + cmd := constructTcpdumpCommand(testCaptureFilePath, bpfFilter) + + // BPF filter should be present as the last argument + if !slices.Contains(cmd.Args, bpfFilter) { + t.Errorf("Expected BPF filter '%s' in command args, but got: %v", bpfFilter, cmd.Args) + } + + // Should have basic structure (tcpdump, -w, path, -i, etc.) + if !slices.Contains(cmd.Args, "tcpdump") { + t.Errorf("Expected 'tcpdump' in command args, but got: %v", cmd.Args) + } + if !slices.Contains(cmd.Args, "-w") { + t.Errorf("Expected '-w' in command args, but got: %v", cmd.Args) + } + + // Verify no user-specified flags with '-' prefix (security check) + for _, arg := range cmd.Args { + // Skip our internal flags and the BPF filter + if arg == "-w" || arg == "-i" || arg == "-s" || arg == "--relinquish-privileges=root" || + arg == testCaptureFilePath || arg == "tcpdump" || arg == "any" || arg == bpfFilter { + continue + } + // Any other argument starting with '-' is suspicious + if strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") { + t.Errorf("Unexpected flag '%s' found in command (only internal flags should be present): %v", arg, cmd.Args) + } + } +} + +// TestTcpdumpFlagsEnvVar tests that TCPDUMP_FLAGS environment variable is correctly parsed +func TestTcpdumpFlagsEnvVar(t *testing.T) { + resetEnvVars() + + tests := []struct { + name string + flagsEnvValue string + expectedFlags []string + }{ + { + name: "single flag", + flagsEnvValue: "-p", + expectedFlags: []string{"-p"}, + }, + { + name: "multiple flags space-separated", + flagsEnvValue: "-p -n -v", + expectedFlags: []string{"-p", "-n", "-v"}, + }, + { + name: "multiple flags with extra spaces", + flagsEnvValue: " -p -n -v ", + expectedFlags: []string{"-p", "-n", "-v"}, + }, + { + name: "flags with arguments", + flagsEnvValue: "-s 96 -p", + expectedFlags: []string{"-s", "96", "-p"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + os.Setenv(captureConstants.TcpdumpFlagsEnvKey, tt.flagsEnvValue) + defer os.Unsetenv(captureConstants.TcpdumpFlagsEnvKey) + + cmd := constructTcpdumpCommand(testCaptureFilePath, "") + + // Check all expected flags are present + for _, expectedFlag := range tt.expectedFlags { + if !slices.Contains(cmd.Args, expectedFlag) { + t.Errorf("Expected flag '%s' in command args, but got: %v", expectedFlag, cmd.Args) + } + } + }) + } +} + +// TestFilterValidation tests flag rejection in filter input +func TestFilterValidation(t *testing.T) { + requireTcpdump(t) + resetEnvVars() + + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + ncp := NewNetworkCaptureProvider(log.Logger().Named("test")).(*NetworkCaptureProvider) + + captureName := testCaptureName + nodeHostName := testNodeHostName + timestamp := file.Now() + ncp.Filename = file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} + tmpCaptureLocation, _ := ncp.Setup(ncp.Filename) + defer os.RemoveAll(tmpCaptureLocation) + + tests := []struct { + name string + setupEnv func() + shouldError bool + errorMsg string + }{ + { + name: "valid BPF filter without flags", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "tcp port 80") + }, + shouldError: false, + }, + { + name: "filter with flag at start", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "-n tcp port 80") + }, + shouldError: true, + errorMsg: "contains flag \"-n\"", + }, + { + name: "filter with flag at end", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "tcp port 80 -n") + }, + shouldError: true, + errorMsg: "contains flag \"-n\"", + }, + { + name: "filter with flag in middle", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "tcp -n port 80") + }, + shouldError: true, + errorMsg: "contains flag \"-n\"", + }, + { + name: "filter with tab-separated flag", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "tcp\t-n\tport 80") + }, + shouldError: true, + errorMsg: "contains flag \"-n\"", + }, + { + name: "filter with newline-separated flag", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "tcp\n-n\nport 80") + }, + shouldError: true, + errorMsg: "contains flag \"-n\"", + }, + { + name: "deprecated tcpdumpFilter with flag", + setupEnv: func() { + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, "-n tcp port 80") + }, + shouldError: true, + errorMsg: "contains flag \"-n\"", + }, + { + name: "complex BPF expression without flags (valid)", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn") + }, + shouldError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resetEnvVars() + tt.setupEnv() + defer resetEnvVars() + + err := ncp.CaptureNetworkPacket(context.Background(), "", 1, 0) + + if tt.shouldError { + if err == nil { + t.Errorf("Expected error containing '%s', but got no error", tt.errorMsg) + } else if !strings.Contains(err.Error(), tt.errorMsg) { + t.Errorf("Expected error containing '%s', but got: %v", tt.errorMsg, err) + } + } else { + // For valid filters, we may get tcpdump execution errors (duration too short, etc.) + // but we should NOT get validation errors + if err != nil && (strings.Contains(err.Error(), "contains flag") || strings.Contains(err.Error(), "whitespace-only")) { + t.Errorf("Expected no validation error, but got: %v", err) + } + } + }) + } +} + +// TestFilterWhitespaceValidation tests whitespace-only filter rejection +func TestFilterWhitespaceValidation(t *testing.T) { + resetEnvVars() + + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + ncp := NewNetworkCaptureProvider(log.Logger().Named("test")).(*NetworkCaptureProvider) + + captureName := "test-capture" + nodeHostName := "test-node" + timestamp := file.Now() + ncp.Filename = file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} + tmpCaptureLocation, _ := ncp.Setup(ncp.Filename) + defer os.RemoveAll(tmpCaptureLocation) + + tests := []struct { + name string + setupEnv func() + }{ + { + name: "pcapFilter with only spaces", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, " ") + }, + }, + { + name: "pcapFilter with only tabs", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "\t\t") + }, + }, + { + name: "pcapFilter with only newlines", + setupEnv: func() { + os.Setenv(captureConstants.PcapFilterEnvKey, "\n\n") + }, + }, + { + name: "tcpdumpFilter with only spaces", + setupEnv: func() { + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, " ") + }, + }, + { + name: "tcpdumpFilter with mixed whitespace", + setupEnv: func() { + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, " \t\n ") + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resetEnvVars() + tt.setupEnv() + defer resetEnvVars() + + err := ncp.CaptureNetworkPacket(context.Background(), "", 1, 0) + + if err == nil { + t.Errorf("Expected error for whitespace-only filter, but got no error") + } else if !errors.Is(err, errTcpdumpFilterEmptyOrWhitespace) { + t.Errorf("Expected errTcpdumpFilterEmptyOrWhitespace, but got: %v", err) + } + }) + } +} + +// TestFilterPrecedence tests that pcapFilter takes precedence over tcpdumpFilter +func TestFilterPrecedence(t *testing.T) { + requireTcpdump(t) + resetEnvVars() + + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + ncp := NewNetworkCaptureProvider(log.Logger().Named("test")).(*NetworkCaptureProvider) + + captureName := testCaptureName + nodeHostName := testNodeHostName + timestamp := file.Now() + ncp.Filename = file.CaptureFilename{CaptureName: captureName, NodeHostname: nodeHostName, StartTimestamp: timestamp} + tmpCaptureLocation, _ := ncp.Setup(ncp.Filename) + defer os.RemoveAll(tmpCaptureLocation) + + tests := []struct { + name string + pcapFilter string + tcpdumpRawFilter string + expectValidationErr bool + }{ + { + name: "both filters set - pcapFilter valid, tcpdumpFilter invalid", + pcapFilter: "tcp port 80", + tcpdumpRawFilter: "-n tcp", + expectValidationErr: false, // Should use pcapFilter, ignore invalid tcpdumpFilter + }, + { + name: "both filters set - pcapFilter invalid, tcpdumpFilter valid", + pcapFilter: "-n tcp", + tcpdumpRawFilter: "tcp port 80", + expectValidationErr: true, // Should validate pcapFilter and reject it + }, + { + name: "only pcapFilter set", + pcapFilter: "tcp port 443", + tcpdumpRawFilter: "", + expectValidationErr: false, + }, + { + name: "only tcpdumpFilter set", + pcapFilter: "", + tcpdumpRawFilter: "udp port 53", + expectValidationErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resetEnvVars() + if tt.pcapFilter != "" { + os.Setenv(captureConstants.PcapFilterEnvKey, tt.pcapFilter) + } + if tt.tcpdumpRawFilter != "" { + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, tt.tcpdumpRawFilter) + } + defer resetEnvVars() + + err := ncp.CaptureNetworkPacket(context.Background(), "", 1, 0) + + if tt.expectValidationErr { + if err == nil || !strings.Contains(err.Error(), "contains flag") { + t.Errorf("Expected validation error, but got: %v", err) + } + } else { + // We expect either no error or a tcpdump execution error (not validation error) + if err != nil && strings.Contains(err.Error(), "contains flag") { + t.Errorf("Unexpected validation error: %v", err) + } + // Other errors (e.g., tcpdump execution failures) are acceptable for these tests + } + }) + } +} + +// TestFilterPrecedenceValue explicitly verifies that the correct filter value is used +func TestFilterPrecedenceValue(t *testing.T) { + resetEnvVars() + + tests := []struct { + name string + pcapFilter string + tcpdumpRawFilter string + expectedFilterUsed string // The filter that should actually appear in the tcpdump command + }{ + { + name: "both set - should use pcapFilter", + pcapFilter: "tcp port 80", + tcpdumpRawFilter: "tcp port 8080", + expectedFilterUsed: "tcp port 80", + }, + { + name: "only pcapFilter set", + pcapFilter: "udp port 53", + tcpdumpRawFilter: "", + expectedFilterUsed: "udp port 53", + }, + { + name: "only tcpdumpFilter set", + pcapFilter: "", + tcpdumpRawFilter: "icmp", + expectedFilterUsed: "icmp", + }, + { + name: "both empty", + pcapFilter: "", + tcpdumpRawFilter: "", + expectedFilterUsed: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resetEnvVars() + if tt.pcapFilter != "" { + os.Setenv(captureConstants.PcapFilterEnvKey, tt.pcapFilter) + } + if tt.tcpdumpRawFilter != "" { + os.Setenv(captureConstants.TcpdumpRawFilterEnvKey, tt.tcpdumpRawFilter) + } + defer resetEnvVars() + + // Construct tcpdump command and check which filter is used + cmd := constructTcpdumpCommand(testCaptureFilePath, tt.expectedFilterUsed) + + // The filter should appear in the command args + if tt.expectedFilterUsed != "" { + found := slices.Contains(cmd.Args, tt.expectedFilterUsed) + if !found { + t.Errorf("Expected filter '%s' in command args, but got: %v", tt.expectedFilterUsed, cmd.Args) + } + } + + // Verify the environment variables are set correctly + pcapEnv := os.Getenv(captureConstants.PcapFilterEnvKey) + tcpdumpEnv := os.Getenv(captureConstants.TcpdumpRawFilterEnvKey) + + if tt.pcapFilter != "" && pcapEnv != tt.pcapFilter { + t.Errorf("Expected PCAP_FILTER='%s', but got '%s'", tt.pcapFilter, pcapEnv) + } + if tt.tcpdumpRawFilter != "" && tcpdumpEnv != tt.tcpdumpRawFilter { + t.Errorf("Expected TCPDUMP_RAW_FILTER='%s', but got '%s'", tt.tcpdumpRawFilter, tcpdumpEnv) + } + + // When both are set, verify pcapFilter env var exists + if tt.pcapFilter != "" && tt.tcpdumpRawFilter != "" { + if pcapEnv == "" { + t.Error("pcapFilter should be set when both filters provided") + } + if pcapEnv != tt.expectedFilterUsed { + t.Errorf("When both filters set, expected to use pcapFilter '%s', but would use '%s'", tt.pcapFilter, tt.expectedFilterUsed) + } + } + }) + } } diff --git a/pkg/capture/provider/network_capture_unix.go b/pkg/capture/provider/network_capture_unix.go index 9a6f6bd207..1c38d36c2c 100644 --- a/pkg/capture/provider/network_capture_unix.go +++ b/pkg/capture/provider/network_capture_unix.go @@ -31,16 +31,27 @@ const ( ) var ( - errTcpdumpCommandNotConstructed = errors.New("tcpdump command is not constructed with expected arguments") - errTcpdumpStopFailed = errors.New("tcpdump stop failed") - errIptablesUnavilable = errors.New("no iptables command is available") - errIptablesLegacySaveFailed = errors.New("failed to run iptables-legacy-save") - errIptablesNftSaveFailed = errors.New("failed to run iptables-nft-save") + errTcpdumpCommandNotConstructed = errors.New("tcpdump command is not constructed with expected arguments") + errTcpdumpStopFailed = errors.New("tcpdump stop failed") + errIptablesUnavilable = errors.New("no iptables command is available") + errIptablesLegacySaveFailed = errors.New("failed to run iptables-legacy-save") + errIptablesNftSaveFailed = errors.New("failed to run iptables-nft-save") + errTcpdumpFilterEmptyOrWhitespace = errors.New("tcpdump filter cannot be empty or whitespace-only") + errTcpdumpFilterContainsFlag = errors.New("filter contains flags which are not allowed") ) -// constructTcpdumpCommand creates a tcpdump command with the appropriate arguments -// based on environment variables for raw filter, specific interfaces, or default behavior -func constructTcpdumpCommand(captureFilePath string) *exec.Cmd { +// constructTcpdumpCommand creates a tcpdump command with the appropriate arguments. +// +// Arguments are added in the following order (order matters for tcpdump): +// 1. Capture control flags (-w, --relinquish-privileges, -s) +// 2. Display/output flags from CaptureOption (read from TCPDUMP_FLAGS env var) +// 3. Interface selection (-i) +// 4. BPF filter expression (MUST BE LAST) +// +// Parameters: +// - captureFilePath: path where the capture file will be written +// - bpfFilter: combined BPF filter expression (user BPF filter + system filter) +func constructTcpdumpCommand(captureFilePath, bpfFilter string) *exec.Cmd { // NOTE(mainred): The tcpdump release of debian:bullseye image, which is for preparing clang and tools, runs as // tcpdump user by default for savefiles for output, but when the binary and library are copied to the distroless // base image, we lost tcpdump user, and the following error will be raised when running tcpdump in our capture pod. @@ -60,25 +71,36 @@ func constructTcpdumpCommand(captureFilePath string) *exec.Cmd { ) } - // If we set flag and value into the arg item of args, the space between flag and value will not treated as part of - // value, for example, "-i eth0" will be treated as "-i" and " eth0", thus brings a tcpdump unknown interface error. - if tcpdumpRawFilter := os.Getenv(captureConstants.TcpdumpRawFilterEnvKey); tcpdumpRawFilter != "" { - tcpdumpRawFilterSlice := strings.Split(tcpdumpRawFilter, " ") - captureStartCmd.Args = append(captureStartCmd.Args, tcpdumpRawFilterSlice...) - } else if specificInterfaces := os.Getenv(captureConstants.CaptureInterfacesEnvKey); specificInterfaces != "" { + // Append tcpdump flags from CaptureOption boolean fields + // These flags are constructed from a controlled mapping table in crd_to_job.go, + // so they're already validated and don't need sanitization here. + if tcpdumpFlags := os.Getenv(captureConstants.TcpdumpFlagsEnvKey); tcpdumpFlags != "" { + flags := strings.Fields(tcpdumpFlags) + captureStartCmd.Args = append(captureStartCmd.Args, flags...) + } + + // Handle interface selection + if specificInterfaces := os.Getenv(captureConstants.CaptureInterfacesEnvKey); specificInterfaces != "" { // Use specific interfaces if provided - interfaceList := strings.Split(specificInterfaces, ",") - for _, iface := range interfaceList { + interfaceList := strings.SplitSeq(specificInterfaces, ",") + for iface := range interfaceList { iface = strings.TrimSpace(iface) if iface != "" { captureStartCmd.Args = append(captureStartCmd.Args, "-i", iface) } } } else { - // Default to capturing on all interfaces if no raw tcpdump filter or specific interfaces are specified + // Default to capturing on all interfaces captureStartCmd.Args = append(captureStartCmd.Args, "-i", "any") } + // SECURITY: bpfFilter contains only BPF filter expressions. + // Any input containing flags (starting with '-') is rejected above. + // Passing bpfFilter as a single argument prevents shell interpretation of special characters. + if bpfFilter != "" { + captureStartCmd.Args = append(captureStartCmd.Args, bpfFilter) + } + return captureStartCmd } @@ -99,6 +121,77 @@ func NewNetworkCaptureProvider(logger *log.ZapLogger) NetworkCaptureProviderInte } } +// obtainAndValidateUserFilter retrieves the user-provided BPF filter from environment variables, +// validates it (rejecting flags), and returns the trimmed filter and its source name. +func (ncp *NetworkCaptureProvider) obtainAndValidateUserFilter() (trimmedFilter, filterSource string, err error) { + pcapFilter := os.Getenv(captureConstants.PcapFilterEnvKey) + tcpdumpRawFilter := os.Getenv(captureConstants.TcpdumpRawFilterEnvKey) + + // PcapFilter takes precedence over TcpdumpFilter + if pcapFilter != "" { + trimmedFilter = strings.TrimSpace(pcapFilter) + filterSource = "pcapFilter" + ncp.l.Info("Using pcapFilter", zap.String("filter", trimmedFilter)) + if tcpdumpRawFilter != "" { + ncp.l.Warn("Both pcapFilter and tcpdumpFilter provided; using pcapFilter (tcpdumpFilter is deprecated and will be removed)", + zap.String("ignored_tcpdumpFilter", tcpdumpRawFilter)) + } + } else if tcpdumpRawFilter != "" { + trimmedFilter = strings.TrimSpace(tcpdumpRawFilter) + filterSource = "tcpdumpFilter (deprecated, will be removed)" + ncp.l.Info("Using deprecated tcpdumpFilter (will be removed); migrate to pcapFilter", zap.String("filter", trimmedFilter)) + } + + // Check for whitespace-only input + if trimmedFilter == "" && (pcapFilter != "" || tcpdumpRawFilter != "") { + return "", "", errTcpdumpFilterEmptyOrWhitespace + } + + // SECURITY: Reject any input containing flags (starting with '-') + // This prevents dangerous flags like -w, -i, -c from being passed to tcpdump + if trimmedFilter != "" { + tokens := strings.FieldsSeq(trimmedFilter) + for token := range tokens { + if strings.HasPrefix(token, "-") { + return "", "", fmt.Errorf("%s contains flag %q: %w", filterSource, token, errTcpdumpFilterContainsFlag) + } + } + } + + return trimmedFilter, filterSource, nil +} + +// combineFilters combines the user filter with the system filter using proper BPF syntax. +func combineFilters(userFilter, systemFilter string) string { + switch { + case userFilter != "" && systemFilter != "": + // Both filters: wrap each in parentheses to ensure correct operator precedence + return fmt.Sprintf("(%s) and (%s)", userFilter, systemFilter) + case userFilter != "": + return userFilter + case systemFilter != "": + return systemFilter + default: + return "" + } +} + +// validateBPFFilterSyntax validates the BPF filter syntax using tcpdump -d. +func (ncp *NetworkCaptureProvider) validateBPFFilterSyntax(ctx context.Context, filter string) error { + if filter == "" { + return nil + } + + //nolint:gosec // G702: tcpdump -d is used for BPF syntax validation only, filter is constructed from validated input + validateCmd := exec.CommandContext(ctx, "tcpdump", "-d", filter) + if err := validateCmd.Run(); err != nil { + ncp.l.Error("BPF filter validation failed", zap.String("filter", filter), zap.Error(err)) + return fmt.Errorf("invalid BPF filter syntax: %w (filter: %q)", err, filter) + } + ncp.l.Info("BPF filter syntax validated successfully", zap.String("filter", filter)) + return nil +} + func (ncp *NetworkCaptureProvider) Setup(filename file.CaptureFilename) (string, error) { captureFolderDir, err := ncp.NetworkCaptureProviderCommon.Setup(filename) if err != nil { @@ -112,7 +205,7 @@ func (ncp *NetworkCaptureProvider) Setup(filename file.CaptureFilename) (string, return ncp.TmpCaptureDir, nil } -func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, filter string, duration, maxSizeMB int) error { +func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, includeExcludeFilter string, duration, maxSizeMB int) error { ctx, cancel := context.WithTimeout(ctx, time.Duration(duration)*time.Second) defer cancel() @@ -122,21 +215,24 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil // Remove the folder in case it already exists to mislead the file size check. os.Remove(captureFilePath) //nolint:errcheck // File may not exist, ok to ignore error - // NOTE(mainred): The tcpdump release of debian:bullseye image, which is for preparing clang and tools, runs as - // tcpdump user by default for savefiles for output, but when the binary and library are copied to the distroless - // base image, we lost tcpdump user, and the following error will be raised when running tcpdump in our capture pod. - // tcpdump: Couldn't find user 'tcpdump' - // To disable this behavior, we use `--relinquish-privileges=root` same as `-Z root`. - // ref: https://manpages.debian.org/bullseye/tcpdump/tcpdump.8.en.html#Z - captureStartCmd := constructTcpdumpCommand(captureFilePath) + // Obtain and validate user-provided BPF filter + userFilter, _, err := ncp.obtainAndValidateUserFilter() + if err != nil { + return err + } - if filter != "" { - captureStartCmd.Args = append( - captureStartCmd.Args, - filter, - ) + // Combine user filter with system filter (include/exclude Pod IPs) + combinedFilter := combineFilters(userFilter, includeExcludeFilter) + + // Validate BPF filter syntax before starting capture + err = ncp.validateBPFFilterSyntax(ctx, combinedFilter) + if err != nil { + return err } + // Construct tcpdump command with combined filter + captureStartCmd := constructTcpdumpCommand(captureFilePath, combinedFilter) + ncp.l.Info("Running tcpdump with args", zap.String("tcpdump command", captureStartCmd.String()), zap.Any("tcpdump args", captureStartCmd.Args)) tcpdumpLogFile, err := ncp.NetworkCaptureProviderCommon.networkCaptureCommandLog("tcpdump.log", captureStartCmd) diff --git a/pkg/capture/provider/network_capture_win.go b/pkg/capture/provider/network_capture_win.go index 1d01adcf7e..9163f8c734 100644 --- a/pkg/capture/provider/network_capture_win.go +++ b/pkg/capture/provider/network_capture_win.go @@ -7,6 +7,7 @@ package provider import ( "context" + "errors" "fmt" "io" "net/http" @@ -24,6 +25,25 @@ import ( "github.com/microsoft/retina/pkg/log" ) +var ( + // netshFilterPattern validates that the filter contains only characters allowed in netsh capture filters. + // Allowed: alphanumeric, dots, colons (for IPv6), parentheses, commas, equals, spaces. + // Rejected: shell metacharacters like &, |, ^, <, >, %, ", ', ;, $, `, \, newlines. + netshFilterPattern = regexp.MustCompile(`^[A-Za-z0-9.=():, ]+$`) + + // ErrInvalidNetshFilter is returned when a netsh filter contains invalid characters. + ErrInvalidNetshFilter = errors.New("filter contains invalid characters; only alphanumeric, dots, colons, parentheses, commas, equals, and spaces are allowed") +) + +// validateNetshFilter validates that a filter string is safe for use with netsh trace commands. +// It rejects filters containing shell metacharacters that could enable command injection. +func validateNetshFilter(filter string) error { + if !netshFilterPattern.MatchString(filter) { + return ErrInvalidNetshFilter + } + return nil +} + type NetworkCaptureProvider struct { NetworkCaptureProviderCommon TmpCaptureDir string @@ -58,32 +78,48 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(duration)) defer cancel() - stopTrace, err := ncp.needToStopTraceSession() + stopTrace, err := ncp.needToStopTraceSession(ctx) if err != nil { return err } if stopTrace { ncp.l.Info("Stopping netsh trace session before starting a new one") - _ = ncp.stopNetworkCapture() + _ = ncp.stopNetworkCapture(ctx) } captureFileName := ncp.Filename.String() + ".etl" captureFilePath := filepath.Join(ncp.TmpCaptureDir, captureFileName) + // SECURITY: Invoke netsh.exe directly without cmd /C to prevent shell injection. + // Build the command args explicitly to avoid shell metacharacter interpretation. captureStartCmd := exec.Command( - "cmd", "/C", - fmt.Sprintf("netsh trace start capture=yes report=disabled overwrite=yes"), + "netsh", + "trace", + "start", + "capture=yes", + "report=disabled", + "overwrite=yes", fmt.Sprintf("tracefile=%s", captureFilePath), ) - // We should split arguments organized in a string delimited by spaces as - // separate ones, otherwise the whole string will be treated as one argument. - // For example, given the following filter, exec lib will treat IPv4.Address - // as the argument and the rest as the value of IPv4.Address. - // "IPv4.Address=(10.244.1.85,10.244.1.235) IPv6.Address=(fd5c:d9f1:79c5:fd83::1bc,fd5c:d9f1:79c5:fd83::11b)" + // Validate and add filter if provided. + // SECURITY: The filter is validated to contain only allowed characters for netsh capture filters. + // This prevents command injection via shell metacharacters like &, |, ^, <, >, etc. if len(filter) != 0 { - netshFilterSlice := strings.Split(filter, " ") - captureStartCmd.Args = append(captureStartCmd.Args, netshFilterSlice...) + // Validate that the filter doesn't start with a hyphen (defense in depth) + if strings.HasPrefix(strings.TrimSpace(filter), "-") { + ncp.l.Warn("Filter starts with hyphen, ignoring to prevent flag injection", zap.String("filter", filter)) + } else { + filterErr := validateNetshFilter(filter) + if filterErr != nil { + ncp.l.Error("Invalid filter for netsh, ignoring", zap.String("filter", filter), zap.Error(filterErr)) + } else { + // Split the filter on spaces and add each token as a separate argument. + // This is safe now because we've validated the filter content. + netshFilterSlice := strings.Split(filter, " ") + captureStartCmd.Args = append(captureStartCmd.Args, netshFilterSlice...) + } + } } // NOTE: netsh cannot stop when the given max size of reach reaches, but we can use maxSizeMB to limit the size of @@ -128,7 +164,7 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil } ncp.l.Info("Stop netsh") - if err := ncp.stopNetworkCapture(); err != nil { + if err := ncp.stopNetworkCapture(ctx); err != nil { ncp.l.Error("Failed to stop netsh trace by 'netsh trace stop', will kill the process", zap.Error(err)) _ = captureStartCmd.Process.Kill() return fmt.Errorf("netsh stop failed: Output: %s", err) @@ -144,8 +180,8 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil // needToStopTraceSession returns true when a running trace session started by Retina capture exists, otherwise returns // false. Specially, when the trace session is not started by Retina capture, determined from the capture file path, an // error will be raised. -func (ncp *NetworkCaptureProvider) needToStopTraceSession() (bool, error) { - command := exec.Command("cmd", "/C", "netsh trace show status") +func (ncp *NetworkCaptureProvider) needToStopTraceSession(ctx context.Context) (bool, error) { + command := exec.CommandContext(ctx, "netsh", "trace", "show", "status") output, err := command.CombinedOutput() // When there's no running trace session, `netsh trace show status` will exist with error code 1, in which case we @@ -168,10 +204,10 @@ func (ncp *NetworkCaptureProvider) needToStopTraceSession() (bool, error) { return false, fmt.Errorf("cannot stop trace session because it's not created by Retina capture") } -func (ncp *NetworkCaptureProvider) stopNetworkCapture() error { +func (ncp *NetworkCaptureProvider) stopNetworkCapture(ctx context.Context) error { ncp.l.Info("Stopping netsh trace session") - command := exec.Command("cmd", "/C", "netsh trace stop") + command := exec.CommandContext(ctx, "netsh", "trace", "stop") output, err := command.CombinedOutput() // ignore the error when stop the trace when no live trace session exists. if strings.Contains(string(output), "There is no trace session currently in progress") { diff --git a/pkg/capture/provider/network_capture_win_test.go b/pkg/capture/provider/network_capture_win_test.go new file mode 100644 index 0000000000..87e3a03fa4 --- /dev/null +++ b/pkg/capture/provider/network_capture_win_test.go @@ -0,0 +1,116 @@ +//go:build windows + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package provider + +import ( + "testing" +) + +func TestValidateNetshFilter(t *testing.T) { + tests := []struct { + name string + filter string + expectErr bool + }{ + { + name: "Valid IPv4 filter", + filter: "IPv4.Address=10.0.0.1", + expectErr: false, + }, + { + name: "Valid IPv4 filter with multiple addresses", + filter: "IPv4.Address=(10.244.1.85,10.244.1.235)", + expectErr: false, + }, + { + name: "Valid IPv6 filter", + filter: "IPv6.Address=(fd5c:d9f1:79c5:fd83::1bc,fd5c:d9f1:79c5:fd83::11b)", + expectErr: false, + }, + { + name: "Valid combined IPv4 and IPv6 filter", + filter: "IPv4.Address=(10.244.1.85,10.244.1.235) IPv6.Address=(fd5c:d9f1:79c5:fd83::1bc,fd5c:d9f1:79c5:fd83::11b)", + expectErr: false, + }, + { + name: "Shell injection with ampersand", + filter: "IPv4.Address=10.0.0.1 & powershell -enc ", + expectErr: true, + }, + { + name: "Shell injection with pipe", + filter: "IPv4.Address=10.0.0.1 | powershell -Command ", + expectErr: true, + }, + { + name: "Shell injection with caret", + filter: "IPv4.Address=10.0.0.1 ^ powershell", + expectErr: true, + }, + { + name: "Shell injection with redirect", + filter: "IPv4.Address=10.0.0.1 > c:\\temp\\output.txt", + expectErr: true, + }, + { + name: "Shell injection with semicolon", + filter: "IPv4.Address=10.0.0.1; powershell", + expectErr: true, + }, + { + name: "Shell injection with dollar sign", + filter: "IPv4.Address=$env:TEMP", + expectErr: true, + }, + { + name: "Shell injection with backtick", + filter: "IPv4.Address=`powershell`", + expectErr: true, + }, + { + name: "Shell injection with double quotes", + filter: "IPv4.Address=\"10.0.0.1\"", + expectErr: true, + }, + { + name: "Shell injection with single quote", + filter: "IPv4.Address='10.0.0.1'", + expectErr: true, + }, + { + name: "Shell injection with percent", + filter: "IPv4.Address=%TEMP%", + expectErr: true, + }, + { + name: "Shell injection with backslash", + filter: "IPv4.Address=10.0.0.1\\powershell", + expectErr: true, + }, + { + name: "Shell injection with newline", + filter: "IPv4.Address=10.0.0.1\npowershell", + expectErr: true, + }, + { + name: "Empty filter", + filter: "", + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validateNetshFilter(tt.filter) + if tt.expectErr && err == nil { + t.Errorf("Expected error for filter '%s', but got none", tt.filter) + } + if !tt.expectErr && err != nil { + t.Errorf("Expected no error for filter '%s', but got: %v", tt.filter, err) + } + }) + } +} From c026aad653999b363f087b21067d9c2bd3be071d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 16:35:12 +0000 Subject: [PATCH 428/448] deps: bump the golang-base group across 6 directories with 1 update (#2370) Bumps the golang-base group with 1 update in the /cli directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /controller directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /hack/tools/kapinger directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /hack/tools/toolbox directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /operator directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /test/image directory: oss/go/microsoft/golang. Updates `oss/go/microsoft/golang` from 1.26.3-azurelinux3.0 to 1.26.3-1-azurelinux3.0 Updates `oss/go/microsoft/golang` from 1.26.3-windowsservercore-ltsc2022 to 1.26.3-1-windowsservercore-ltsc2022 Updates `oss/go/microsoft/golang` from 1.26.3 to 1.26.3-1 Updates `oss/go/microsoft/golang` from 1.26.3 to 1.26.3-1 Updates `oss/go/microsoft/golang` from 1.26.3-azurelinux3.0 to 1.26.3-1-azurelinux3.0 Updates `oss/go/microsoft/golang` from 1.26.3-azurelinux3.0 to 1.26.3-1-azurelinux3.0 Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- hack/tools/kapinger/Dockerfile | 4 ++-- hack/tools/toolbox/Dockerfile | 2 +- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- test/image/Dockerfile | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index e4febdd144..95197283ec 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index 86ba5ae443..cf772095ad 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:9230290079612a2a8d30a0aa8b8f097c3194e787d09987df0c3e6b8f6271ee27 AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index aebe3c43ce..a5006b691d 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 77d478c65e..3be03e15fc 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 87172128b2..22e413b052 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:22617ad636077ab971853e1b61ff610cde773d3e6e1a10075fe7c4fdfde1f1b1 AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-windowsservercore-ltsc2022@sha256:6dd6f9178eb2cd736ba6da106294d934b178c6e62263845abf46e7727d47651e AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index c2f67e42c4..54f016fd35 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022@sha256:22617ad636077ab971853e1b61ff610cde773d3e6e1a10075fe7c4fdfde1f1b1 AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-windowsservercore-ltsc2022@sha256:6dd6f9178eb2cd736ba6da106294d934b178c6e62263845abf46e7727d47651e AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index ab33c2b97c..d3bcd61a0c 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3@sha256:9cb93c7fc65fcec28b0af140bd4e42510e7553dd67718289dfee2a955986b7e3 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:e6e1c95302de09c2f0f6ea1ada9cee207d6cac9b506df5d289a29b103b0a2539 AS builder WORKDIR /build ADD . . @@ -17,7 +17,7 @@ CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3@sha256:9cb93c7fc65fcec28b0af140bd4e42510e7553dd67718289dfee2a955986b7e3 AS windows-builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:e6e1c95302de09c2f0f6ea1ada9cee207d6cac9b506df5d289a29b103b0a2539 AS windows-builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 0aea90b01c..8164c19486 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3@sha256:9cb93c7fc65fcec28b0af140bd4e42510e7553dd67718289dfee2a955986b7e3 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:e6e1c95302de09c2f0f6ea1ada9cee207d6cac9b506df5d289a29b103b0a2539 AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index f9d0e1de1f..0ea338d518 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index bbc6fa5559..e6cf417d8b 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index f54716ec0a..9b561c3ebc 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0@sha256:2329aeebbce4d25c81d006067e1da74a43552600a7b0e25475ace1b797b3ba42 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina From 94d341bba56fc08973ee855c8485a76b76fbbb0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 16:35:33 +0000 Subject: [PATCH 429/448] deps: bump goreleaser/goreleaser-action from 7.2.1 to 7.2.2 in the actions-patch group (#2369) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the actions-patch group with 1 update: [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action). Updates `goreleaser/goreleaser-action` from 7.2.1 to 7.2.2
Release notes

Sourced from goreleaser/goreleaser-action's releases.

v7.2.2

What's Changed

New Contributors

Full Changelog: https://github.com/goreleaser/goreleaser-action/compare/v7...v7.2.2

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=goreleaser/goreleaser-action&package-manager=github_actions&previous-version=7.2.1&new-version=7.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index c758d38e3c..fa2ab1c3b1 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -31,7 +31,7 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser build - uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1 + uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2 env: MCR_AGENT_IMAGE_NAME: mcr.microsoft.com/containernetworking/retina-agent with: @@ -55,7 +55,7 @@ jobs: - name: Install Syft uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - name: Run GoReleaser release - uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1 + uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2 with: distribution: goreleaser version: latest From 3b50857a24814fc1567f9614daa974428554ad31 Mon Sep 17 00:00:00 2001 From: carlotaarvela <67275927+carlotaarvela@users.noreply.github.com> Date: Thu, 21 May 2026 17:59:37 +0100 Subject: [PATCH 430/448] feat(capture): Add --cleanup-after-upload flag for automatic resource cleanup (#2367) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Adds a `--cleanup-after-upload` flag to `kubectl retina capture create` that enables automatic cleanup of capture jobs, secrets, and host-path files after successful upload to remote storage (blob, S3, or PVC). **Key behaviors:** - **TTL on jobs** (no-wait mode): When `--cleanup-after-upload` is combined with `--no-wait=true` and a remote destination, jobs get a `TTLSecondsAfterFinished` (5 min) so Kubernetes garbage-collects them automatically. - **Secret ownerReferences** (always): Secrets created for blob/S3 uploads always get ownerReferences pointing to the capture job, ensuring they are cleaned up when the job is deleted—whether by TTL, manual delete, or the controller. - **Controller auto-delete**: The operator's `CaptureReconciler` now deletes the Capture resource once all jobs succeed and `CleanUpAfterUpload` is true with remote storage configured (blob, S3, or PVC). - **ActiveDeadlineSeconds**: Jobs now get a hard deadline (`duration + 30min`) to prevent indefinite hangs. - **Wait timeout fix**: `waitUntilJobsComplete` deadline is now `duration + 5min` (floored at 5min), fixing premature timeouts for short captures. - **NotFound tolerance**: `deleteSecret` and `capture delete` now tolerate `NotFound` errors caused by ownerRef garbage collection racing with explicit deletion. ## Related Issue N/A — feature request for safer automated capture workflows. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ### Unit Tests All tests pass in the affected packages. The new logic is 100% covered by the new CLI and Operator controller tests added. ### Manual Testing | # | Scenario | Command | Expected | Result | |---|----------|---------|----------|--------| | 1 | `--cleanup-after-upload` without remote | `./bin/kubectl-retina capture create --name test1 --node-names aks-nodepool1-... --host-path /tmp/captures --cleanup-after-upload --duration 5s` | Error: requires remote storage | **PASS** — error returned immediately | | 2 | No-wait + blob + cleanup | `./bin/kubectl-retina capture create --name test2 --node-names aks-nodepool1-... --blob-upload "" --cleanup-after-upload --no-wait=true --duration 10s` | CLI exits immediately, job has TTL, secret has ownerRef | **PASS** — verified via `kubectl get job -o yaml` (TTL=300), `kubectl get secret -o yaml` (ownerReferences present), job auto-deleted after ~5 min | | 3 | Wait + blob + cleanup | `./bin/kubectl-retina capture create --name test3 --node-names aks-nodepool1-... --blob-upload "" --cleanup-after-upload --no-wait=false --duration 10s` | CLI waits, uploads blob, then deletes jobs/secrets | **PASS** — CLI printed completion, `kubectl get jobs` showed no jobs remaining, blob appeared in storage account, secret deleted | | 4 | Wait + blob WITHOUT cleanup | `./bin/kubectl-retina capture create --name test4 --node-names aks-nodepool1-... --blob-upload "" --no-wait=false --duration 10s` | CLI waits, uploads, jobs/secrets remain | **PASS** — jobs and secrets preserved after CLI exit | | 5 | Host-path only + no-wait (no cleanup flag) | `./bin/kubectl-retina capture create --name test5 --node-names aks-nodepool1-... --host-path /tmp/captures --no-wait=true --duration 5s` | No TTL set, jobs remain | **PASS** — `kubectl get job -o yaml` showed no TTLSecondsAfterFinished | **Wait timeout fix verified:** Test 3 used `--duration 10s` and the CLI completed within ~75s (10s capture + upload time), confirming the new `duration + 5min` deadline works correctly for short captures (previously would timeout at 2×duration = 20s before upload finished). **NotFound tolerance verified:** In test 2, running `kubectl retina capture delete --name test2` after TTL had already garbage-collected the job+secret returned success (no "secret not found" error). ## Additional Notes - The `CleanUpAfterUpload` field is added to the CRD spec as optional with `+kubebuilder:default=false`. Existing Captures are unaffected. - `JobActiveDeadlineBufferSeconds` (30 min) is generous to accommodate large captures uploading over slow links or Windows nodes with slow image pulls. - The operator controller cleanup path only triggers when ALL jobs succeed — any failure preserves everything for debugging. - The controller's remote storage check includes all three types: `BlobUpload`, `S3Upload`, and `PersistentVolumeClaim`. --- cli/cmd/capture/capture.go | 1 + cli/cmd/capture/cleanup_after_upload_test.go | 289 +++++++++++ cli/cmd/capture/create.go | 139 +++++- cli/cmd/capture/create_test.go | 382 ++++++++++++++ cli/cmd/capture/delete.go | 5 +- cli/cmd/capture/delete_test.go | 62 +++ crd/api/v1alpha1/capture_types.go | 8 + .../helm/retina/crds/retina.sh_captures.yaml | 21 +- docs/04-Captures/02-cli.md | 20 + docs/04-Captures/03-crd.md | 22 + .../capture/cleanup_after_upload_test.go | 468 ++++++++++++++++++ .../operator/capture/controller.go | 26 +- 12 files changed, 1429 insertions(+), 14 deletions(-) create mode 100644 cli/cmd/capture/cleanup_after_upload_test.go create mode 100644 pkg/controllers/operator/capture/cleanup_after_upload_test.go diff --git a/cli/cmd/capture/capture.go b/cli/cmd/capture/capture.go index 32af373e5f..83017feb80 100644 --- a/cli/cmd/capture/capture.go +++ b/cli/cmd/capture/capture.go @@ -85,6 +85,7 @@ type Opts struct { genericclioptions.ConfigFlags Name *string blobUpload string + cleanUpAfterUpload bool debug bool duration time.Duration excludeFilter string diff --git a/cli/cmd/capture/cleanup_after_upload_test.go b/cli/cmd/capture/cleanup_after_upload_test.go new file mode 100644 index 0000000000..ace7b15e5c --- /dev/null +++ b/cli/cmd/capture/cleanup_after_upload_test.go @@ -0,0 +1,289 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "bytes" + "context" + "fmt" + "testing" + + "github.com/microsoft/retina/pkg/label" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + clienttesting "k8s.io/client-go/testing" +) + +func newFakeClientForCleanupTests() *fake.Clientset { + objects := []runtime.Object{ + NewNode("node1"), + NewNamespace("default"), + } + + kubeClient := fake.NewClientset(objects...) + + // Handle job creation to set job name and quickly mark as completed + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction, ok := action.(clienttesting.CreateAction) + if !ok { + return false, nil, fmt.Errorf("expected CreateAction, got %T", action) //nolint:err113 // test code + } + job := createAction.GetObject().(*batchv1.Job) + + // Set job name if unset + if job.Name == "" { + job.Name = job.GenerateName + randomString(5) + } + // Mark job as completed immediately for cleanup tests + now := metav1.Now() + job.Status.CompletionTime = &now + job.Status.Conditions = []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + } + return false, job, nil + }) + + // Handle secret creation to set name from GenerateName + kubeClient.PrependReactor("create", "secrets", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction, ok := action.(clienttesting.CreateAction) + if !ok { + return false, nil, fmt.Errorf("expected CreateAction, got %T", action) //nolint:err113 // test code + } + secret := createAction.GetObject().(*corev1.Secret) + + // Set secret name if unset (mimics real k8s behavior with GenerateName) + if secret.Name == "" { + secret.Name = secret.GenerateName + randomString(5) + } + return false, secret, nil + }) + + return kubeClient +} + +func TestCleanupAfterUpload_RequiresRemoteStorage(t *testing.T) { + // When --cleanup-after-upload is set without remote storage, it should fail + kubeClient := newFakeClientForCleanupTests() + cmd := NewCommand(kubeClient) + + cmd.SetArgs([]string{ + "create", + "--name=test-cleanup", + "--namespace=default", + "--node-names=node1", + "--host-path=captures", + "--cleanup-after-upload", + "--duration=5s", + }) + + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + err := cmd.Execute() + require.Error(t, err) + assert.Contains(t, err.Error(), "--cleanup-after-upload requires remote storage (--blob-upload, --s3-bucket, or --pvc)") +} + +func TestCleanupAfterUpload_WithBlobUpload(t *testing.T) { + // When --cleanup-after-upload is set with blob upload, command should succeed + // and jobs should be created (controller handles cleanup after upload) + kubeClient := newFakeClientForCleanupTests() + cmd := NewCommand(kubeClient) + + cmd.SetArgs([]string{ + "create", + "--name=test-cleanup-blob", + "--namespace=default", + "--node-names=node1", + "--blob-upload=https://testaccount.blob.core.windows.net/container?sv=2021-06-08&ss=b&srt=co&sp=rwdlacitfx&se=2099-01-01", + "--cleanup-after-upload", + "--duration=5s", + }) + + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + err := cmd.Execute() + require.NoError(t, err) + + // Verify jobs were created (controller handles cleanup after upload completes) + jobs, err := kubeClient.BatchV1().Jobs("default").List(context.TODO(), metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", label.CaptureNameLabel, "test-cleanup-blob"), + }) + require.NoError(t, err) + assert.NotEmpty(t, jobs.Items, "jobs should be created for capture") +} + +func TestCleanupAfterUpload_WithS3Upload(t *testing.T) { + // When --cleanup-after-upload is set with S3 upload, command should succeed + kubeClient := newFakeClientForCleanupTests() + cmd := NewCommand(kubeClient) + + cmd.SetArgs([]string{ + "create", + "--name=test-cleanup-s3", + "--namespace=default", + "--node-names=node1", + "--s3-bucket=test-bucket", + "--s3-region=us-east-1", + "--s3-access-key-id=AKIAIOSFODNN7EXAMPLE", + "--s3-secret-access-key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "--cleanup-after-upload", + "--duration=5s", + }) + + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + err := cmd.Execute() + require.NoError(t, err) + + // Verify jobs were created (controller handles cleanup after upload completes) + jobs, err := kubeClient.BatchV1().Jobs("default").List(context.TODO(), metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", label.CaptureNameLabel, "test-cleanup-s3"), + }) + require.NoError(t, err) + assert.NotEmpty(t, jobs.Items, "jobs should be created for capture") +} + +func TestCleanupAfterUpload_RespectsNoWait(t *testing.T) { + // When --cleanup-after-upload is set with --no-wait=true (default), + // the CLI should not block. TTL + owner refs handle cleanup. + kubeClient := newFakeClientForCleanupTests() + cmd := NewCommand(kubeClient) + + cmd.SetArgs([]string{ + "create", + "--name=test-cleanup-nowait", + "--namespace=default", + "--node-names=node1", + "--blob-upload=https://testaccount.blob.core.windows.net/container?sv=2021-06-08&ss=b&srt=co&sp=rwdlacitfx&se=2099-01-01", + "--cleanup-after-upload", + "--no-wait=true", + "--duration=5s", + }) + + buf := new(bytes.Buffer) + cmd.SetOut(buf) + + err := cmd.Execute() + require.NoError(t, err) + + // Verify jobs still exist (CLI returns immediately in no-wait mode, + // TTL and owner references handle automatic cleanup) + jobs, err := kubeClient.BatchV1().Jobs("default").List(context.TODO(), metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", label.CaptureNameLabel, "test-cleanup-nowait"), + }) + require.NoError(t, err) + assert.NotEmpty(t, jobs.Items, "jobs should exist because CLI returned immediately in no-wait mode") +} + +func TestCleanupAfterUpload_DefaultIsFalse(t *testing.T) { + // Without --cleanup-after-upload flag, the default should be false + assert.False(t, DefaultCleanUpAfterUpload) +} + +func TestCleanupAfterUpload_FlagRegistered(t *testing.T) { + // Verify the flag is properly registered on the create subcommand + kubeClient := fake.NewClientset() + cmd := NewCommand(kubeClient) + + // Find the create subcommand + var createCmd *cobra.Command + for _, sub := range cmd.Commands() { + if sub.Name() == "create" { + createCmd = sub + break + } + } + require.NotNil(t, createCmd, "create subcommand should exist") + + flag := createCmd.Flags().Lookup("cleanup-after-upload") + require.NotNil(t, flag, "cleanup-after-upload flag should be registered") + assert.Equal(t, "false", flag.DefValue) + assert.Contains(t, flag.Usage, "clean up capture jobs") +} + +func TestCleanupAfterUpload_TTLSetInNoWaitMode(t *testing.T) { + // When --cleanup-after-upload with --no-wait=true and remote destination, + // jobs should have TTLSecondsAfterFinished set. + kubeClient := newFakeClientForCleanupTests() + + var createdJob *batchv1.Job + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction := action.(clienttesting.CreateAction) + job := createAction.GetObject().(*batchv1.Job) + if job.Name == "" { + job.Name = job.GenerateName + "test3" + } + now := metav1.Now() + job.Status.CompletionTime = &now + createdJob = job + return false, job, nil + }) + + cmd := NewCommand(kubeClient) + cmd.SetArgs([]string{ + "create", + "--name=test-ttl", + "--namespace=default", + "--node-names=node1", + "--blob-upload=https://testaccount.blob.core.windows.net/container?sv=2021-06-08", + "--cleanup-after-upload", + "--no-wait=true", + "--duration=5s", + }) + + err := cmd.Execute() + require.NoError(t, err) + require.NotNil(t, createdJob) + + require.NotNil(t, createdJob.Spec.TTLSecondsAfterFinished, "TTL should be set in no-wait mode with remote destination") + assert.Equal(t, JobTTLSecondsAfterFinished, *createdJob.Spec.TTLSecondsAfterFinished) +} + +func TestCleanupAfterUpload_NoTTLWhenHostPathOnly(t *testing.T) { + // When only host-path is configured (no remote), TTL should NOT be set + // even in no-wait mode, because the user needs the job to find their capture file. + kubeClient := newFakeClientForCleanupTests() + + var createdJob *batchv1.Job + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction := action.(clienttesting.CreateAction) + job := createAction.GetObject().(*batchv1.Job) + if job.Name == "" { + job.Name = job.GenerateName + "test4" + } + now := metav1.Now() + job.Status.CompletionTime = &now + createdJob = job + return false, job, nil + }) + + cmd := NewCommand(kubeClient) + cmd.SetArgs([]string{ + "create", + "--name=test-no-ttl", + "--namespace=default", + "--node-names=node1", + "--host-path=captures", + "--no-wait=true", + "--duration=5s", + }) + + err := cmd.Execute() + require.NoError(t, err) + require.NotNil(t, createdJob) + + assert.Nil(t, createdJob.Spec.TTLSecondsAfterFinished, "TTL should NOT be set when only host-path is configured") +} diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index a42d9c99d1..bb1cbfafb4 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -16,8 +16,10 @@ import ( "go.uber.org/zap" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/kubectl/pkg/util/i18n" @@ -34,8 +36,9 @@ import ( ) const ( - DefaultDebug bool = false - DefaultDuration time.Duration = 1 * time.Minute + DefaultCleanUpAfterUpload bool = false + DefaultDebug bool = false + DefaultDuration time.Duration = 1 * time.Minute // DefaultHostPath is the default subpath (joined under DefaultHostPathBaseDir on // the node) where capture artifacts are stored. It is a bare name, not an // absolute path: absolute paths are rejected by the operator. @@ -52,8 +55,33 @@ const ( DefaultS3Path string = "retina/captures" DefaultWaitPeriod time.Duration = 1 * time.Minute DefaultWaitTimeout time.Duration = 5 * time.Minute + + // JobTTLSecondsAfterFinished is how long completed/failed jobs and their + // pods are kept before Kubernetes garbage-collects them (no-wait mode). + JobTTLSecondsAfterFinished int32 = 300 // 5 minutes + + // JobActiveDeadlineBufferSeconds is added to the capture duration to form + // the Job's activeDeadlineSeconds. This buffer accounts for output upload + // and cleanup time after the capture itself finishes. + JobActiveDeadlineBufferSeconds int64 = 1800 // 30 minutes + + // WaitDeadlineBuffer is extra time added to the capture duration when + // computing the wait deadline, to account for upload and scheduling overhead. + WaitDeadlineBuffer time.Duration = 5 * time.Minute + + // MinPollAttempts is the minimum number of polling iterations before the + // wait deadline expires. Used to compute a fallback poll period. + MinPollAttempts = 4 ) +var errCleanupRequiresRemoteStorage = errors.New("--cleanup-after-upload requires remote storage (--blob-upload, --s3-bucket, or --pvc)") + +// hasRemoteDestination returns true if the capture options specify a remote +// storage output (blob upload or S3 upload). +func hasRemoteDestination(o *Opts) bool { + return o.blobUpload != "" || o.s3Bucket != "" || o.pvc != "" +} + var createExample = templates.Examples(i18n.T(` # Select nodes by node name and copy the artifacts to the node host path # (joined under the operator-configured base directory; default /var/log/retina/captures/testcapture) @@ -114,18 +142,29 @@ func create(kubeClient kubernetes.Interface) error { return err } + if opts.cleanUpAfterUpload { + if !hasRemoteDestination(&opts) { + return errCleanupRequiresRemoteStorage + } + } + jobsCreated, err := createJobs(ctx, kubeClient, capture) if err != nil { retinacmd.Logger.Error("Failed to create job", zap.Error(err)) return err } + + // Set owner references on secrets so they are garbage-collected when the + // jobs are removed (by TTL, explicit deletion, or manual kubectl delete). + if ownerRefErr := setSecretOwnerReferences(ctx, kubeClient, capture, jobsCreated); ownerRefErr != nil { + retinacmd.Logger.Error("Failed to set owner references on capture secrets", zap.Error(ownerRefErr)) + } + if opts.nowait { - retinacmd.Logger.Info("Please manually delete all capture jobs") - if capture.Spec.OutputConfiguration.BlobUpload != nil { - retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload)) - } - if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { - retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName)) + if opts.cleanUpAfterUpload && hasRemoteDestination(&opts) { + retinacmd.Logger.Info("Capture jobs will be automatically cleaned up after upload (TTL-based)") + } else { + retinacmd.Logger.Info("Please manually delete all capture jobs (associated secrets will be garbage-collected automatically)") } printCaptureResult(jobsCreated) return nil @@ -271,6 +310,8 @@ func NewCreateSubCommand(kubeClient kubernetes.Interface) *cobra.Command { createCapture.Flags().BoolVar(&opts.includeMetadata, "include-metadata", DefaultIncludeMetadata, "If true, collect static network metadata into capture file") createCapture.Flags().IntVar(&opts.jobNumLimit, "job-num-limit", DefaultJobNumLimit, "The maximum number of jobs can be created for each capture. 0 means no limit") createCapture.Flags().BoolVar(&opts.nowait, "no-wait", DefaultNowait, "Do not wait for the long-running capture job to finish") + createCapture.Flags().BoolVar(&opts.cleanUpAfterUpload, "cleanup-after-upload", DefaultCleanUpAfterUpload, + "Automatically clean up capture jobs and resources after successful upload to remote storage") createCapture.Flags().BoolVar(&opts.debug, "debug", DefaultDebug, "When debug is true, a customized retina-agent image, determined by the environment variable RETINA_AGENT_IMAGE, is set") return createCapture @@ -322,7 +363,11 @@ func deleteSecret(ctx context.Context, kubeClient kubernetes.Interface, secretNa return nil } - return kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(ctx, *secretName, metav1.DeleteOptions{}) //nolint:wrapcheck //internal return + err := kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(ctx, *secretName, metav1.DeleteOptions{}) + if k8serrors.IsNotFound(err) { + return nil + } + return err //nolint:wrapcheck //internal return } // validateBPFFilter checks that a BPF filter string doesn't contain flags (tokens starting with '-'). @@ -571,6 +616,8 @@ func createCaptureF(ctx context.Context, kubeClient kubernetes.Interface) (*reti includeFilterSlice := strings.Split(opts.includeFilter, ",") capture.Spec.CaptureConfiguration.Filters.Include = includeFilterSlice } + + capture.Spec.CleanUpAfterUpload = opts.cleanUpAfterUpload return capture, nil } @@ -593,6 +640,21 @@ func createJobs(ctx context.Context, kubeClient kubernetes.Interface, capture *r jobsCreated := []batchv1.Job{} for _, job := range jobs { + // In no-wait mode with a remote destination, set TTL so Kubernetes + // auto-deletes completed jobs and their pods. When host-path only, + // the job metadata is needed to locate the capture file. + if opts.nowait && opts.cleanUpAfterUpload && hasRemoteDestination(&opts) { + ttl := JobTTLSecondsAfterFinished + job.Spec.TTLSecondsAfterFinished = &ttl + } + + // Set a hard deadline to prevent jobs from running indefinitely if the + // capture process hangs. Deadline = capture duration + upload buffer. + if opts.duration > 0 { + deadline := int64(opts.duration.Seconds()) + JobActiveDeadlineBufferSeconds + job.Spec.ActiveDeadlineSeconds = &deadline + } + jobCreated, err := kubeClient.BatchV1().Jobs(*opts.Namespace).Create(ctx, job, metav1.CreateOptions{}) if err != nil { return nil, err @@ -609,7 +671,12 @@ func waitUntilJobsComplete(ctx context.Context, kubeClient kubernetes.Interface, // TODO: let's make the timeout and period to wait for all job to finish configurable. deadline := DefaultWaitTimeout if opts.duration != 0 { - deadline = opts.duration * 2 + // Allow time for capture + upload + scheduling overhead (Windows + // nodes in particular need extra time for image pull and pod start). + deadline = opts.duration + WaitDeadlineBuffer + if deadline < DefaultWaitTimeout { + deadline = DefaultWaitTimeout + } } period := DefaultWaitPeriod @@ -617,6 +684,10 @@ func waitUntilJobsComplete(ctx context.Context, kubeClient kubernetes.Interface, if period < opts.duration/10 { period = opts.duration / 10 } + // Ensure poll period is less than the deadline so we get multiple checks. + if period >= deadline { + period = deadline / MinPollAttempts + } retinacmd.Logger.Info(fmt.Sprintf("Waiting timeout is set to %s", deadline)) ctx, cancel := context.WithTimeout(ctx, deadline) @@ -672,3 +743,51 @@ func deleteJobs(ctx context.Context, kubeClient kubernetes.Interface, jobs []bat } return jobsFailedtoDelete } + +// setSecretOwnerReferences adds ownerReferences from the given jobs to the +// secrets used by the capture (blob or S3). This ensures secrets are garbage- +// collected when the owning jobs are deleted (by TTL or explicitly). +func setSecretOwnerReferences(ctx context.Context, kubeClient kubernetes.Interface, capture *retinav1alpha1.Capture, jobs []batchv1.Job) error { + var secretNames []string + if capture.Spec.OutputConfiguration.BlobUpload != nil { + secretNames = append(secretNames, *capture.Spec.OutputConfiguration.BlobUpload) + } + if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { + secretNames = append(secretNames, capture.Spec.OutputConfiguration.S3Upload.SecretName) + } + + if len(secretNames) == 0 || len(jobs) == 0 { + return nil + } + + ownerRefs := make([]metav1.OwnerReference, 0, len(jobs)) + for i := range jobs { + ownerRefs = append(ownerRefs, metav1.OwnerReference{ + APIVersion: batchv1.SchemeGroupVersion.String(), + Kind: "Job", + Name: jobs[i].Name, + UID: jobs[i].UID, + }) + } + + for _, secretName := range secretNames { + secret, err := kubeClient.CoreV1().Secrets(*opts.Namespace).Get(ctx, secretName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("failed to get secret %s: %w", secretName, err) + } + // Deduplicate owner references to avoid appending the same refs on retries. + existing := make(map[types.UID]struct{}, len(secret.OwnerReferences)) + for _, ref := range secret.OwnerReferences { + existing[ref.UID] = struct{}{} + } + for _, ref := range ownerRefs { + if _, found := existing[ref.UID]; !found { + secret.OwnerReferences = append(secret.OwnerReferences, ref) + } + } + if _, err := kubeClient.CoreV1().Secrets(*opts.Namespace).Update(ctx, secret, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update secret %s with owner references: %w", secretName, err) + } + } + return nil +} diff --git a/cli/cmd/capture/create_test.go b/cli/cmd/capture/create_test.go index add7118a25..dff8bab2b9 100644 --- a/cli/cmd/capture/create_test.go +++ b/cli/cmd/capture/create_test.go @@ -24,6 +24,8 @@ import ( clienttesting "k8s.io/client-go/testing" ) +const testNamespace = "test-ns" + type testcase struct { name string inputName string @@ -674,3 +676,383 @@ func TestCreateCaptureCommand_AbsoluteHostPath_ShouldFail(t *testing.T) { require.Contains(t, err.Error(), "OutputConfiguration.HostPath", "error should reference the rejected HostPath field; got: %v", err) } +func TestHasRemoteDestination(t *testing.T) { + tests := []struct { + name string + opts Opts + want bool + }{ + { + name: "blob upload is remote", + opts: Opts{blobUpload: "https://account.blob.core.windows.net/container"}, + want: true, + }, + { + name: "s3 bucket is remote", + opts: Opts{s3Bucket: "my-bucket"}, + want: true, + }, + { + name: "pvc is remote", + opts: Opts{pvc: "my-pvc"}, + want: true, + }, + { + name: "host-path only is not remote", + opts: Opts{hostPath: "/mnt/captures"}, + want: false, + }, + { + name: "empty opts is not remote", + opts: Opts{}, + want: false, + }, + { + name: "multiple remote destinations", + opts: Opts{blobUpload: "https://x.blob.core.windows.net/c", s3Bucket: "bucket"}, + want: true, + }, + } + + for i := range tests { + t.Run(tests[i].name, func(t *testing.T) { + require.Equal(t, tests[i].want, hasRemoteDestination(&tests[i].opts)) + }) + } +} + +func TestSetSecretOwnerReferences(t *testing.T) { + ns := testNamespace + secretName := "blob-secret-abc" + + kubeClient := fake.NewClientset( + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: ns, + }, + }, + ) + + origNs := opts.Namespace + opts.Namespace = &ns + defer func() { opts.Namespace = origNs }() + + blobUpload := secretName + capture := &retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + BlobUpload: &blobUpload, + }, + }, + } + + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "job-1", + Namespace: ns, + UID: "uid-1", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "job-2", + Namespace: ns, + UID: "uid-2", + }, + }, + } + + err := setSecretOwnerReferences(context.Background(), kubeClient, capture, jobs) + require.NoError(t, err) + + secret, err := kubeClient.CoreV1().Secrets(ns).Get(context.Background(), secretName, metav1.GetOptions{}) + require.NoError(t, err) + require.Len(t, secret.OwnerReferences, 2, "secret should have owner references for both jobs") + require.Equal(t, "job-1", secret.OwnerReferences[0].Name) + require.Equal(t, "job-2", secret.OwnerReferences[1].Name) + require.Equal(t, "batch/v1", secret.OwnerReferences[0].APIVersion) + require.Equal(t, "Job", secret.OwnerReferences[0].Kind) +} + +func TestSetSecretOwnerReferences_Idempotent(t *testing.T) { + ns := testNamespace + secretName := "blob-secret-idem" + + kubeClient := fake.NewClientset( + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: ns, + }, + }, + ) + + origNs := opts.Namespace + opts.Namespace = &ns + defer func() { opts.Namespace = origNs }() + + blobUpload := secretName + capture := &retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + BlobUpload: &blobUpload, + }, + }, + } + + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "job-1", + Namespace: ns, + UID: "uid-1", + }, + }, + } + + // Call twice to simulate retry/re-reconcile. + err := setSecretOwnerReferences(context.Background(), kubeClient, capture, jobs) + require.NoError(t, err) + err = setSecretOwnerReferences(context.Background(), kubeClient, capture, jobs) + require.NoError(t, err) + + secret, err := kubeClient.CoreV1().Secrets(ns).Get(context.Background(), secretName, metav1.GetOptions{}) + require.NoError(t, err) + require.Len(t, secret.OwnerReferences, 1, "duplicate owner references should not be added") +} + +func TestSetSecretOwnerReferences_NoSecrets(t *testing.T) { + kubeClient := fake.NewClientset() + + capture := &retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{}, + }, + } + + err := setSecretOwnerReferences(context.Background(), kubeClient, capture, []batchv1.Job{}) + require.NoError(t, err) +} + +func TestSetSecretOwnerReferences_S3Secret(t *testing.T) { + ns := testNamespace + secretName := "s3-secret-xyz" + + kubeClient := fake.NewClientset( + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: ns, + }, + }, + ) + + origNs := opts.Namespace + opts.Namespace = &ns + defer func() { opts.Namespace = origNs }() + + capture := &retinav1alpha1.Capture{ + Spec: retinav1alpha1.CaptureSpec{ + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + S3Upload: &retinav1alpha1.S3Upload{ + SecretName: secretName, + Bucket: "my-bucket", + }, + }, + }, + } + + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "job-a", + Namespace: ns, + UID: "uid-a", + }, + }, + } + + err := setSecretOwnerReferences(context.Background(), kubeClient, capture, jobs) + require.NoError(t, err) + + secret, err := kubeClient.CoreV1().Secrets(ns).Get(context.Background(), secretName, metav1.GetOptions{}) + require.NoError(t, err) + require.Len(t, secret.OwnerReferences, 1, "secret should have owner reference for the job") + require.Equal(t, "job-a", secret.OwnerReferences[0].Name) + require.Equal(t, "batch/v1", secret.OwnerReferences[0].APIVersion) + require.Equal(t, "Job", secret.OwnerReferences[0].Kind) +} + +func TestDeleteSecret_NotFound(t *testing.T) { + // deleteSecret should return nil when the secret doesn't exist + ns := testNamespace + kubeClient := fake.NewClientset() // no secrets pre-created + + origNs := opts.Namespace + opts.Namespace = &ns + defer func() { opts.Namespace = origNs }() + + name := "nonexistent-secret" + err := deleteSecret(context.Background(), kubeClient, &name) + require.NoError(t, err, "deleteSecret should not error on NotFound") +} + +func TestDeleteSecret_NilName(t *testing.T) { + ns := testNamespace + kubeClient := fake.NewClientset() + + origNs := opts.Namespace + opts.Namespace = &ns + defer func() { opts.Namespace = origNs }() + + err := deleteSecret(context.Background(), kubeClient, nil) + require.NoError(t, err, "deleteSecret should return nil for nil secretName") +} + +func TestDeleteSecret_ExistingSecret(t *testing.T) { + // deleteSecret should succeed when the secret exists + ns := testNamespace + secretName := "my-secret" + kubeClient := fake.NewClientset( + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: ns, + }, + }, + ) + + origNs := opts.Namespace + opts.Namespace = &ns + defer func() { opts.Namespace = origNs }() + + err := deleteSecret(context.Background(), kubeClient, &secretName) + require.NoError(t, err) + + // Verify secret is deleted + _, err = kubeClient.CoreV1().Secrets(ns).Get(context.Background(), secretName, metav1.GetOptions{}) + require.Error(t, err, "secret should be gone after deleteSecret") +} + +func TestCreateJobs_ActiveDeadlineSeconds(t *testing.T) { + // When duration > 0, jobs should have ActiveDeadlineSeconds set + kubeClient := newFakeClientForCleanupTests() + + var createdJob *batchv1.Job + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction := action.(clienttesting.CreateAction) + job := createAction.GetObject().(*batchv1.Job) + if job.Name == "" { + job.Name = job.GenerateName + "test" + } + now := metav1.Now() + job.Status.CompletionTime = &now + createdJob = job + return false, job, nil + }) + + cmd := NewCommand(kubeClient) + cmd.SetArgs([]string{ + "create", + "--name=test-deadline", + "--namespace=default", + "--node-names=node1", + "--host-path=captures", + "--no-wait=true", + "--duration=60s", + }) + + err := cmd.Execute() + require.NoError(t, err) + require.NotNil(t, createdJob) + require.NotNil(t, createdJob.Spec.ActiveDeadlineSeconds, + "ActiveDeadlineSeconds should be set when duration > 0") + // 60s + 1800s buffer = 1860 + require.Equal(t, int64(1860), *createdJob.Spec.ActiveDeadlineSeconds) +} + +func TestCreateJobs_NoTTLWithoutCleanupFlag(t *testing.T) { + // When --cleanup-after-upload is NOT set, TTL should NOT be set + // even with remote + no-wait. + kubeClient := newFakeClientForCleanupTests() + + var createdJob *batchv1.Job + kubeClient.PrependReactor("create", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + createAction := action.(clienttesting.CreateAction) + job := createAction.GetObject().(*batchv1.Job) + if job.Name == "" { + job.Name = job.GenerateName + "test" + } + now := metav1.Now() + job.Status.CompletionTime = &now + createdJob = job + return false, job, nil + }) + + cmd := NewCommand(kubeClient) + cmd.SetArgs([]string{ + "create", + "--name=test-no-cleanup", + "--namespace=default", + "--node-names=node1", + "--blob-upload=https://testaccount.blob.core.windows.net/container?sv=2021-06-08", + "--no-wait=true", + "--duration=5s", + // NOTE: --cleanup-after-upload is NOT set + }) + + err := cmd.Execute() + require.NoError(t, err) + require.NotNil(t, createdJob) + require.Nil(t, createdJob.Spec.TTLSecondsAfterFinished, + "TTL should NOT be set without --cleanup-after-upload") +} + +func TestWaitUntilJobsComplete_ShortDuration(t *testing.T) { + // Verifies that waitUntilJobsComplete uses a deadline of at least + // DefaultWaitTimeout (5min), and completes quickly when jobs are already done. + // This exercises the deadline calculation (duration + 5min, floored at DefaultWaitTimeout) + // and the period clamping logic. + kubeClient := newFakeClientForCleanupTests() + + // The fake client's reactor already marks jobs as completed on create. + // For the "get" call inside waitUntilJobsComplete, we need the job to appear completed. + kubeClient.PrependReactor("get", "jobs", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + getAction := action.(clienttesting.GetAction) + job := &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: getAction.GetName(), + Namespace: getAction.GetNamespace(), + }, + Status: batchv1.JobStatus{ + CompletionTime: &metav1.Time{}, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + } + return true, job, nil + }) + + cmd := NewCommand(kubeClient) + cmd.SetArgs([]string{ + "create", + "--name=test-wait-short", + "--namespace=default", + "--node-names=node1", + "--host-path=captures", + "--no-wait=false", + "--duration=2s", + }) + + // This should complete quickly (within seconds) because the fake client + // reports jobs as already completed. If the deadline/period logic is broken, + // this would hang until the test timeout. + err := cmd.Execute() + require.NoError(t, err) +} diff --git a/cli/cmd/capture/delete.go b/cli/cmd/capture/delete.go index 8c2b3fd0ab..4e90147a54 100644 --- a/cli/cmd/capture/delete.go +++ b/cli/cmd/capture/delete.go @@ -15,6 +15,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "go.uber.org/zap" + k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" @@ -77,7 +78,9 @@ func NewDeleteSubCommand(kubeClient kubernetes.Interface) *cobra.Command { for idx := range jobList.Items[0].Spec.Template.Spec.Volumes { if jobList.Items[0].Spec.Template.Spec.Volumes[idx].Secret != nil { if err := kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(ctx, jobList.Items[0].Spec.Template.Spec.Volumes[idx].Secret.SecretName, metav1.DeleteOptions{}); err != nil { - return errors.Wrap(err, "failed to delete capture secret") + if !k8serrors.IsNotFound(err) { + return errors.Wrap(err, "failed to delete capture secret") + } } break } diff --git a/cli/cmd/capture/delete_test.go b/cli/cmd/capture/delete_test.go index 2a8bdc4f9a..f346758b26 100644 --- a/cli/cmd/capture/delete_test.go +++ b/cli/cmd/capture/delete_test.go @@ -11,6 +11,7 @@ import ( "github.com/microsoft/retina/pkg/label" batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" @@ -190,3 +191,64 @@ func TestDeleteCaptureJobs(t *testing.T) { }) } } + +func TestDeleteCaptureJobs_SecretAlreadyDeleted(t *testing.T) { + // When a secret referenced by a job's volume has already been deleted + // (e.g. via ownerRef GC), the delete command should still succeed. + deleteTestCapName := "test-secret-gone" + ns := "default" + + kubeClient := newKubeclient() + + // Create a job that references a secret volume, but don't create the secret itself. + secretName := "already-deleted-secret" + job := &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: deleteTestCapName + "-node1-abcde", + Namespace: ns, + Labels: map[string]string{ + label.CaptureNameLabel: deleteTestCapName, + label.AppLabel: "capture", + }, + }, + Spec: batchv1.JobSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{Name: "capture", Image: "test"}}, + Volumes: []corev1.Volume{ + { + Name: "capture-secret", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secretName, + }, + }, + }, + }, + RestartPolicy: corev1.RestartPolicyNever, + }, + }, + }, + } + + _, err := kubeClient.BatchV1().Jobs(ns).Create(context.Background(), job, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Failed to create test job: %v", err) + } + + // Run delete — the secret doesn't exist, so the NotFound check is exercised + deleteCmd := NewCommand(kubeClient) + deleteCmd.SetArgs([]string{"delete", "--name", deleteTestCapName, "--namespace", ns}) + buf := new(bytes.Buffer) + deleteCmd.SetOut(buf) + + err = deleteCmd.Execute() + if err != nil { + t.Fatalf("Delete should succeed even when secret is already gone, got: %v", err) + } + + // Verify job was deleted + if jobExists(t, kubeClient, deleteTestCapName, ns) { + t.Error("Expected job to be deleted") + } +} diff --git a/crd/api/v1alpha1/capture_types.go b/crd/api/v1alpha1/capture_types.go index c16eaea0d7..c90ecf7958 100644 --- a/crd/api/v1alpha1/capture_types.go +++ b/crd/api/v1alpha1/capture_types.go @@ -272,6 +272,14 @@ type CaptureSpec struct { CaptureConfiguration CaptureConfiguration `json:"captureConfiguration"` // +kubebuilder:validation:Required OutputConfiguration OutputConfiguration `json:"outputConfiguration,omitempty"` + // CleanUpAfterUpload indicates whether the capture jobs and associated resources + // should be automatically cleaned up after a successful upload to remote storage + // (BlobUpload or S3Upload). When set to true, completed capture jobs, secrets, + // and the Capture resource itself will be deleted once all jobs have succeeded + // and uploads are confirmed. + // +optional + // +kubebuilder:default=false + CleanUpAfterUpload bool `json:"cleanUpAfterUpload,omitempty"` } // +kubebuilder:object:root=true diff --git a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml index 64c414b5dc..c38fd357df 100644 --- a/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml +++ b/deploy/standard/manifests/controller/helm/retina/crds/retina.sh_captures.yaml @@ -368,6 +368,15 @@ spec: required: - captureTarget type: object + cleanUpAfterUpload: + default: false + description: |- + CleanUpAfterUpload indicates whether the capture jobs and associated resources + should be automatically cleaned up after a successful upload to remote storage + (BlobUpload or S3Upload). When set to true, completed capture jobs, secrets, + and the Capture resource itself will be deleted once all jobs have succeeded + and uploads are confirmed. + type: boolean outputConfiguration: description: OutputConfiguration indicates the location capture will be stored. @@ -378,8 +387,16 @@ spec: type: string hostPath: description: |- - HostPath stores the capture files into the specified host filesystem. - If nothing exists at the given path of the host, an empty directory will be created there. + HostPath is a relative subpath name (e.g. "my-capture") joined under the + operator-configured host base directory (default /var/log/retina/captures) + on every node that runs a capture pod. The capture files are written to + that joined directory, and an empty directory is created there if it does + not already exist. + + HostPath must be a relative subpath: absolute paths (e.g. "/tmp/foo", + "C:\\foo") and any value containing ".." segments are rejected by the + operator. CR authors cannot influence the base directory, which is + controlled by the cluster operator via the operator config. type: string persistentVolumeClaim: description: PersistentVolumeClaim mounts the supplied PVC into diff --git a/docs/04-Captures/02-cli.md b/docs/04-Captures/02-cli.md index ed761631ab..144a2c963a 100644 --- a/docs/04-Captures/02-cli.md +++ b/docs/04-Captures/02-cli.md @@ -59,6 +59,7 @@ The network traffic will be uploaded to the specified output location. | Flag | Type | Default | Description | Notes | |-----------------------|------------|----------|-----------------------------------------------------------------------------|-------| | `blob-upload` | string | "" | Blob SAS URL with write permission to upload capture files. | | +| `cleanup-after-upload` | bool | false | Automatically clean up capture files from the node's host path after successful upload to remote storage (blob or S3). Requires a remote storage destination. | | | `debug` | bool | false | When debug is true, a customized retina-agent image, determined by the environment variable RETINA_AGENT_IMAGE, is set. | | | `duration` | string | 1m0s | Maximum duration of the packet capture - in minutes / seconds. | | | `exclude-filter` | string | "" | A comma-separated list of IP:Port pairs that are excluded from capturing network packets. Supported formats are IP:Port, IP, Port, *:Port, IP:* | Only works on Linux. | @@ -547,3 +548,22 @@ kubectl retina capture create \ When creating a capture, you can specify `--no-wait` to clean up the jobs after the Capture is completed. Otherwise, after creating a Capture, a random Capture name is returned, with which you can delete the jobs by running the `kubectl retina capture delete` command. + +### Automatic Cleanup After Upload + +When using `--cleanup-after-upload` with a remote storage destination (`--blob-upload`, `--s3-bucket`, or `--pvc`), Retina will automatically delete the capture files from the node's host path after the data has been successfully uploaded to remote storage. + +This flag works with both `--no-wait=true` (default) and `--no-wait=false`: + +- **`--no-wait=true`** (default): The CLI exits immediately. Jobs are assigned a TTL (5 minutes after completion) so Kubernetes automatically garbage-collects them along with their secrets. +- **`--no-wait=false`**: The CLI waits for all jobs to complete, then deletes the jobs and secrets itself. + +In both modes, the capture agent removes the host-path files once the upload succeeds. + +```shell +kubectl retina capture create --name my-capture --node-names "node1" \ + --blob-upload "" \ + --cleanup-after-upload +``` + +If any capture job fails, the host-path files are preserved for debugging. diff --git a/docs/04-Captures/03-crd.md b/docs/04-Captures/03-crd.md index 5b372878a0..8807afeecb 100644 --- a/docs/04-Captures/03-crd.md +++ b/docs/04-Captures/03-crd.md @@ -150,3 +150,25 @@ spec: ``` Additional examples can also be found in the [GitHub capture samples](https://github.com/microsoft/retina/tree/main/samples/capture). + +## Automatic Cleanup After Upload + +Set `cleanUpAfterUpload: true` in the Capture spec to have the controller automatically delete the Capture resource and all associated jobs once all capture jobs complete successfully and data has been uploaded to remote storage (Blob, S3, or PVC). + +```yaml +apiVersion: retina.sh/v1alpha1 +kind: Capture +metadata: + name: my-capture +spec: + captureConfiguration: + captureTarget: + nodeSelector: + matchLabels: + kubernetes.io/os: linux + outputConfiguration: + blobUpload: "" + cleanUpAfterUpload: true +``` + +If any job fails, the Capture resource and jobs are preserved for debugging. This option requires a remote storage output (`blobUpload`, `s3Upload`, or `persistentVolumeClaim`). diff --git a/pkg/controllers/operator/capture/cleanup_after_upload_test.go b/pkg/controllers/operator/capture/cleanup_after_upload_test.go new file mode 100644 index 0000000000..2c3dbb0b28 --- /dev/null +++ b/pkg/controllers/operator/capture/cleanup_after_upload_test.go @@ -0,0 +1,468 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package capture + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" + + retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1" + "github.com/microsoft/retina/pkg/log" +) + +const testSecretName = "test-secret" + +func newScheme() *runtime.Scheme { + s := runtime.NewScheme() + _ = retinav1alpha1.AddToScheme(s) + _ = batchv1.AddToScheme(s) + _ = corev1.AddToScheme(s) + return s +} + +func newTestReconciler(objects ...runtime.Object) *CaptureReconciler { + _, _ = log.SetupZapLogger(log.GetDefaultLogOpts()) + scheme := newScheme() + + clientObjects := make([]client.Object, 0, len(objects)) + for _, obj := range objects { + clientObjects = append(clientObjects, obj.(client.Object)) + } + + fakeClient := fakeclient.NewClientBuilder(). + WithScheme(scheme). + WithObjects(clientObjects...). + WithStatusSubresource(&retinav1alpha1.Capture{}, &batchv1.Job{}). + Build() + + return &CaptureReconciler{ + Client: fakeClient, + scheme: scheme, + logger: log.Logger().Named("capture-test"), + } +} + +func TestCleanUpAfterUpload_AllJobsSucceeded_WithBlobUpload(t *testing.T) { + secretName := testSecretName + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + BlobUpload: &secretName, + }, + CleanUpAfterUpload: true, + }, + } + + completionTime := metav1.Now() + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + CompletionTime: &completionTime, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // The capture should have been deleted (triggering the finalizer cleanup) + deletedCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture", Namespace: "default"}, deletedCapture) + assert.True(t, err != nil || deletedCapture.DeletionTimestamp != nil, + "capture should be deleted or marked for deletion when CleanUpAfterUpload is true and all jobs succeeded") +} + +func TestCleanUpAfterUpload_AllJobsSucceeded_WithS3Upload(t *testing.T) { + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-s3", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + S3Upload: &retinav1alpha1.S3Upload{ + Bucket: "test-bucket", + SecretName: "test-s3-secret", + Region: "us-east-1", + }, + }, + CleanUpAfterUpload: true, + }, + } + + completionTime := metav1.Now() + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-s3-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + CompletionTime: &completionTime, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // The capture should have been deleted + deletedCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture-s3", Namespace: "default"}, deletedCapture) + assert.True(t, err != nil || deletedCapture.DeletionTimestamp != nil, + "capture should be deleted when CleanUpAfterUpload is true with S3 upload and all jobs succeeded") +} + +func TestCleanUpAfterUpload_NotTriggeredWhenFalse(t *testing.T) { + secretName := testSecretName + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-no-cleanup", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + BlobUpload: &secretName, + }, + CleanUpAfterUpload: false, + }, + } + + completionTime := metav1.Now() + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-no-cleanup-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + CompletionTime: &completionTime, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // Capture should still exist since CleanUpAfterUpload is false + existingCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture-no-cleanup", Namespace: "default"}, existingCapture) + require.NoError(t, err) + assert.Nil(t, existingCapture.DeletionTimestamp, "capture should NOT be deleted when CleanUpAfterUpload is false") +} + +func TestCleanUpAfterUpload_NotTriggeredOnFailedJobs(t *testing.T) { + secretName := testSecretName + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-failed", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + BlobUpload: &secretName, + }, + CleanUpAfterUpload: true, + }, + } + + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-failed-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobFailed, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // Capture should still exist since jobs failed + existingCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture-failed", Namespace: "default"}, existingCapture) + require.NoError(t, err) + assert.Nil(t, existingCapture.DeletionTimestamp, "capture should NOT be deleted when jobs failed") +} + +func TestCleanUpAfterUpload_NotTriggeredWithoutRemoteStorage(t *testing.T) { + hostPath := "/mnt/captures" + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-local", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + HostPath: &hostPath, + }, + CleanUpAfterUpload: true, + }, + } + + completionTime := metav1.Now() + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-local-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + CompletionTime: &completionTime, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // Capture should still exist since there's no remote storage + existingCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture-local", Namespace: "default"}, existingCapture) + require.NoError(t, err) + assert.Nil(t, existingCapture.DeletionTimestamp, "capture should NOT be deleted when only local storage is used") +} + +func TestCleanUpAfterUpload_AllJobsSucceeded_WithPVC(t *testing.T) { + pvcName := "test-pvc" + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-pvc", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + PersistentVolumeClaim: &pvcName, + }, + CleanUpAfterUpload: true, + }, + } + + completionTime := metav1.Now() + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-pvc-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + CompletionTime: &completionTime, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // The capture should have been deleted + deletedCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture-pvc", Namespace: "default"}, deletedCapture) + assert.True(t, err != nil || deletedCapture.DeletionTimestamp != nil, + "capture should be deleted when CleanUpAfterUpload is true with PVC and all jobs succeeded") +} + +func TestCleanUpAfterUpload_MixedJobResults_NotTriggered(t *testing.T) { + secretName := testSecretName + capture := &retinav1alpha1.Capture{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-mixed", + Namespace: "default", + Finalizers: []string{captureFinalizer}, + }, + Spec: retinav1alpha1.CaptureSpec{ + CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ + CaptureTarget: retinav1alpha1.CaptureTarget{ + NodeSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/role": "agent", + }, + }, + }, + }, + OutputConfiguration: retinav1alpha1.OutputConfiguration{ + BlobUpload: &secretName, + }, + CleanUpAfterUpload: true, + }, + } + + completionTime := metav1.Now() + jobs := []batchv1.Job{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-mixed-job-1", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + CompletionTime: &completionTime, + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobComplete, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-capture-mixed-job-2", + Namespace: "default", + }, + Status: batchv1.JobStatus{ + Conditions: []batchv1.JobCondition{ + { + Type: batchv1.JobFailed, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + } + + reconciler := newTestReconciler(capture) + ctx := context.Background() + + _, err := reconciler.updateCaptureStatusFromJobs(ctx, capture, jobs) + require.NoError(t, err) + + // Capture should still exist since one job failed + existingCapture := &retinav1alpha1.Capture{} + err = reconciler.Get(ctx, types.NamespacedName{Name: "test-capture-mixed", Namespace: "default"}, existingCapture) + require.NoError(t, err) + assert.Nil(t, existingCapture.DeletionTimestamp, "capture should NOT be deleted when some jobs failed even if others succeeded") +} diff --git a/pkg/controllers/operator/capture/controller.go b/pkg/controllers/operator/capture/controller.go index 1e83311610..8e2079d99c 100644 --- a/pkg/controllers/operator/capture/controller.go +++ b/pkg/controllers/operator/capture/controller.go @@ -215,7 +215,31 @@ func (cr *CaptureReconciler) updateCaptureStatusFromJobs(ctx context.Context, ca } } capture.Status.CompletionTime = &lastCompleteTime - return cr.updateStatus(ctx, capture) + if result, err := cr.updateStatus(ctx, capture); err != nil { + return result, err + } + + // If CleanUpAfterUpload is enabled and all jobs succeeded (uploaded to remote storage), + // automatically delete the Capture resource which triggers cleanup via the finalizer. + if !capture.Spec.CleanUpAfterUpload || len(failedJobs) != 0 { + return ctrl.Result{}, nil + } + + hasRemoteStorage := capture.Spec.OutputConfiguration.BlobUpload != nil || + capture.Spec.OutputConfiguration.S3Upload != nil || + capture.Spec.OutputConfiguration.PersistentVolumeClaim != nil + if !hasRemoteStorage { + return ctrl.Result{}, nil + } + + cr.logger.Info("All capture jobs completed successfully with remote storage upload, performing automatic cleanup", + zap.String("Capture", captureRef.String())) + if err := cr.Delete(ctx, capture); err != nil { + cr.logger.Error("Failed to auto-delete Capture after successful upload", + zap.Error(err), zap.String("Capture", captureRef.String())) + return ctrl.Result{}, fmt.Errorf("failed to auto-delete Capture after successful upload: %w", err) + } + return ctrl.Result{}, nil } func (cr *CaptureReconciler) createJobsFromCapture(ctx context.Context, capture *retinav1alpha1.Capture) (ctrl.Result, error) { From b99355d571b825b8d7a70726ebdf6caf8fcfb7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Larivi=C3=A8re?= Date: Thu, 21 May 2026 14:45:05 -0400 Subject: [PATCH 431/448] feat(operator): scope leader election to release namespace (#2244) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Scopes the retina operator's leader election lease to the Helm release namespace instead of the hardcoded `kube-system`, and tightens the associated RBAC from a `ClusterRole` to a namespaced `Role`. * Moved lease permissions from ClusterRole (cluster-wide) to a namespaced Role, scoped to the release namespace * Removed hardcoded kube-system, auto-detected from the service account token or overridable via `--leader-election-namespace` / `operator.leaderElectionNamespace` Helm value * Exposed `operator.replicas` as a Helm value instead of being hardcoded to 1 ## Breaking Changes RBAC scope reduced from `ClusterRole` to namespaced `Role` Lease permissions are no longer granted cluster-wide. The `ClusterRole` `retina-operator-clusterrole` is replaced by a namespaced `Role` `retina-operator-role` scoped to the release namespace. Leader election lease moved from `kube-system` to the release namespace The `cilium-operator-resource-lock` lease will no longer be created in `kube-system`. The stale lease must be manually removed after upgrading: ```bash kubectl delete lease cilium-operator-resource-lock -n kube-system ``` `--leader-election-namespace` is now required for all deployments. Raw `kubectl apply`, Kustomize, or any other non-Helm deployment method must explicitly pass `--leader-election-namespace` or the operator will fail to start. ### Migration Path For a no-op upgrade (zero disruption, preserves existing behaviour), set the following in your Helm values before upgrading: ```yaml operator: leaderElectionNamespace: kube-system ``` ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed ### leader-election-namespace ``` $ kubectl get deployment retina-operator -n retina -o jsonpath='{.spec.template.spec.containers[0].command} {.spec.template.spec.containers[0].args}' ["/retina-operator"] ["manage-cilium-crds","--config-dir","/retina","--leader-election-namespace=retina"]% $ kubectl get lease -n retina NAME HOLDER AGE cilium-operator-resource-lock retina-operator-64978b666b-j6fcv-npZoUmPWHB 7m10s $ kubectl logs -n retina -l control-plane=retina-operator --tail=-1 | grep cilium-operator-resource-lock time=2026-05-15T20:16:14.278736868Z level=info msg="\"Attempting to acquire leader lease...\" lock=\"retina/cilium-operator-resource-lock\"" subsys=klog time=2026-05-15T20:16:14.292364352Z level=info msg="\"Successfully acquired lease\" lock=\"retina/cilium-operator-resource-lock\"" subsys=klog ``` ### Missing leader-election-namespace argument error ``` $ kubectl logs -n retina -l control-plane=retina-operator --tail=-1 | grep leader-election-namespace ts=2026-05-15T20:36:55.905Z level=info caller=option/config.go:1134 msg=" --leader-election-namespace=''" subsys=retina-operator ts=2026-05-15T20:36:55.908Z level=error caller=cell/invoke.go:52 msg="Invoke failed" error="--leader-election-namespace must be set" errorVerbose="--leader-election-namespace must be set\ngithub.com/microsoft/retina/operator/cmd/cilium-crds.init\n\t:1\nruntime.doInit1\n\t/usr/local/go/src/runtime/proc.go:8103\nruntime.doInit\n\t/usr/local/go/src/runtime/proc.go:8070\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:258\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1771" function="cilium-crds.registerOperatorHooks (cmd/cilium-crds/root_linux.go:66)" stacktrace="log/slog.(*Logger).Error\n\t/usr/local/go/src/log/slog/logger.go:229\ngithub.com/cilium/hive/cell.(*invoker).invoke\n\t/go/pkg/mod/github.com/cilium/hive@v0.0.0-20260108104938-97756f6ff54c/cell/invoke.go:52\ngithub.com/cilium/hive/cell.(*invoker).Apply.func1\n\t/go/pkg/mod/github.com/cilium/hive@v0.0.0-20260108104938-97756f6ff54c/cell/invoke.go:67\ngithub.com/cilium/hive.(*Hive).Populate\n\t/go/pkg/mod/github.com/cilium/hive@v0.0.0-20260108104938-97756f6ff54c/hive.go:349\ngithub.com/cilium/hive.(*Hive).Start\n\t/go/pkg/mod/github.com/cilium/hive@v0.0.0-20260108104938-97756f6ff54c/hive.go:379\ngithub.com/cilium/hive.(*Hive).Run\n\t/go/pkg/mod/github.com/cilium/hive@v0.0.0-20260108104938-97756f6ff54c/hive.go:259\ngithub.com/microsoft/retina/operator/cmd/cilium-crds.Execute\n\t/workspace/operator/cmd/cilium-crds/root_linux.go:61\ngithub.com/microsoft/retina/operator/cmd.init.func1\n\t/workspace/operator/cmd/cilium_crds_cmd_linux.go:23\ngithub.com/spf13/cobra.(*Command).execute\n\t/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1019\ngithub.com/spf13/cobra.(*Command).ExecuteC\n\t/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1148\ngithub.com/spf13/cobra.(*Command).Execute\n\t/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1071\ngithub.com/microsoft/retina/operator/cmd.Execute\n\t/workspace/operator/cmd/root.go:49\nmain.main\n\t/workspace/operator/main.go:9\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:290" ts=2026-05-15T20:36:55.908Z level=error caller=logging/slog.go:159 msg="failed to start: failed to populate object graph: --leader-election-namespace must be set" subsys=retina-operator stacktrace="log/slog.(*Logger).Log\n\t/usr/local/go/src/log/slog/logger.go:189\ngithub.com/cilium/cilium/pkg/logging.Fatal\n\t/go/pkg/mod/github.com/cilium/cilium@v1.19.3/pkg/logging/slog.go:159\ngithub.com/microsoft/retina/operator/cmd/cilium-crds.Execute\n\t/workspace/operator/cmd/cilium-crds/root_linux.go:62\ngithub.com/microsoft/retina/operator/cmd.init.func1\n\t/workspace/operator/cmd/cilium_crds_cmd_linux.go:23\ngithub.com/spf13/cobra.(*Command).execute\n\t/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1019\ngithub.com/spf13/cobra.(*Command).ExecuteC\n\t/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1148\ngithub.com/spf13/cobra.(*Command).Execute\n\t/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1071\ngithub.com/microsoft/retina/operator/cmd.Execute\n\t/workspace/operator/cmd/root.go:49\nmain.main\n\t/workspace/operator/main.go:9\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:290" ``` ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Sébastien Larivière Co-authored-by: Quang Nguyen --- .../templates/operator/clusterrole.yaml | 17 +---------- .../operator/clusterrolebinding.yaml | 2 +- .../retina/templates/operator/deployment.yaml | 8 +++-- .../helm/retina/templates/operator/role.yaml | 30 +++++++++++++++++++ .../templates/operator/rolebinding.yaml | 23 ++++++++++++++ .../controller/helm/retina/values.yaml | 4 +++ operator/cilium-crds/config/config_linux.go | 11 ++++--- operator/cmd/cilium-crds/cells_linux.go | 2 -- operator/cmd/cilium-crds/root_linux.go | 25 +++++++++++----- 9 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 deploy/hubble/manifests/controller/helm/retina/templates/operator/role.yaml create mode 100644 deploy/hubble/manifests/controller/helm/retina/templates/operator/rolebinding.yaml diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml index 395bb0bb2f..d2e12e7c9e 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrole.yaml @@ -3,7 +3,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: creationTimestamp: null - name: retina-operator-role + name: retina-operator-clusterrole rules: - apiGroups: - "apiextensions.k8s.io" @@ -100,19 +100,4 @@ rules: - get - list - watch - # For cilium-operator running in HA mode. - # - # Cilium operator running in HA mode requires the use of ResourceLock for Leader Election - # between multiple running instances. - # The preferred way of doing this is to use LeasesResourceLock as edits to Leases are less - # common and fewer objects in the cluster watch "all Leases". - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - get - - update - {{- end -}} diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrolebinding.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrolebinding.yaml index 3138f41fbf..a67b2a1c99 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrolebinding.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/operator/clusterrolebinding.yaml @@ -13,7 +13,7 @@ metadata: roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: retina-operator-role + name: retina-operator-clusterrole subjects: - kind: ServiceAccount name: retina-operator diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/operator/deployment.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/operator/deployment.yaml index e44a535c81..acea3cb711 100644 --- a/deploy/hubble/manifests/controller/helm/retina/templates/operator/deployment.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/templates/operator/deployment.yaml @@ -17,7 +17,7 @@ spec: selector: matchLabels: control-plane: retina-operator - replicas: 1 + replicas: {{ .Values.operator.replicas }} template: metadata: annotations: @@ -56,16 +56,18 @@ spec: {{- end }} {{ else }} command: - - /retina-operator + - /retina-operator {{- end }} {{- if .Values.operator.container.args}} args: {{- range $.Values.operator.container.args}} - {{ . | quote }} {{- end}} - {{ else }} + - --leader-election-namespace={{ $.Values.operator.leaderElectionNamespace | default $.Release.Namespace }} + {{- else }} args: - --config-dir=/retina + - --leader-election-namespace={{ .Values.operator.leaderElectionNamespace | default .Release.Namespace }} {{- end}} env: # this env var is used by retina OSS telemetry and zap diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/operator/role.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/operator/role.yaml new file mode 100644 index 0000000000..6ffecf4a26 --- /dev/null +++ b/deploy/hubble/manifests/controller/helm/retina/templates/operator/role.yaml @@ -0,0 +1,30 @@ +{{- if .Values.operator.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/name: role + app.kubernetes.io/instance: retina-operator-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: operator + app.kubernetes.io/part-of: operator + app.kubernetes.io/managed-by: kustomize + name: retina-operator-role + namespace: {{ .Values.operator.leaderElectionNamespace | default .Release.Namespace }} +rules: + # For cilium-operator running in HA mode. + # + # Cilium operator running in HA mode requires the use of ResourceLock for Leader Election + # between multiple running instances. + # The preferred way of doing this is to use LeasesResourceLock as edits to Leases are less + # common and fewer objects in the cluster watch "all Leases". + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update + +{{- end -}} diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/operator/rolebinding.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/operator/rolebinding.yaml new file mode 100644 index 0000000000..911e9cbaee --- /dev/null +++ b/deploy/hubble/manifests/controller/helm/retina/templates/operator/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- if .Values.operator.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/name: rolebinding + app.kubernetes.io/instance: retina-operator-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: operator + app.kubernetes.io/part-of: operator + app.kubernetes.io/managed-by: kustomize + name: retina-operator-rolebinding + namespace: {{ .Values.operator.leaderElectionNamespace | default .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: retina-operator-role +subjects: +- kind: ServiceAccount + name: retina-operator + namespace: {{ .Values.namespace }} + +{{- end -}} diff --git a/deploy/hubble/manifests/controller/helm/retina/values.yaml b/deploy/hubble/manifests/controller/helm/retina/values.yaml index 0967106ab8..d7258dac61 100644 --- a/deploy/hubble/manifests/controller/helm/retina/values.yaml +++ b/deploy/hubble/manifests/controller/helm/retina/values.yaml @@ -16,6 +16,7 @@ os: # FIXME: remove unnecessary pieces, etc. operator: enabled: true + replicas: 1 repository: acndev.azurecr.io/retina-operator pullPolicy: Always tag: "latest" @@ -32,6 +33,9 @@ operator: # -- Node tolerations for pod assignment on nodes with taints # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ tolerations: [] + # Namespace used for operator leader election lease. + # Defaults to .Release.Namespace when empty. + leaderElectionNamespace: "" agent: leaderElection: false diff --git a/operator/cilium-crds/config/config_linux.go b/operator/cilium-crds/config/config_linux.go index bb73d7aff4..9774343578 100644 --- a/operator/cilium-crds/config/config_linux.go +++ b/operator/cilium-crds/config/config_linux.go @@ -8,19 +8,22 @@ import ( ) type Config struct { - EnableTelemetry bool - LeaderElection bool + EnableTelemetry bool + LeaderElection bool + LeaderElectionNamespace string } func (c Config) Flags(flags *pflag.FlagSet) { flags.Bool("enable-telemetry", c.EnableTelemetry, "enable telemetry (send logs and metrics to a remote server)") flags.Bool("leader-election", c.LeaderElection, "Enable leader election for operator. Ensures there is only one active operator Pod") + flags.String("leader-election-namespace", c.LeaderElectionNamespace, "Namespace for the leader election lease. Required when leader election is enabled.") } var ( DefaultConfig = Config{ - EnableTelemetry: false, - LeaderElection: false, + EnableTelemetry: false, + LeaderElection: false, + LeaderElectionNamespace: "", } Cell = cell.Module( diff --git a/operator/cmd/cilium-crds/cells_linux.go b/operator/cmd/cilium-crds/cells_linux.go index 4339a1b8ee..d250ba9272 100644 --- a/operator/cmd/cilium-crds/cells_linux.go +++ b/operator/cmd/cilium-crds/cells_linux.go @@ -42,8 +42,6 @@ import ( "github.com/cilium/statedb" ) -const operatorK8sNamespace = "kube-system" - var ( Operator = cell.Module( "operator", diff --git a/operator/cmd/cilium-crds/root_linux.go b/operator/cmd/cilium-crds/root_linux.go index 7cbc570d5c..ee24b5efec 100644 --- a/operator/cmd/cilium-crds/root_linux.go +++ b/operator/cmd/cilium-crds/root_linux.go @@ -26,6 +26,7 @@ import ( "github.com/cilium/cilium/pkg/option" "github.com/cilium/hive/cell" "github.com/microsoft/retina/internal/buildinfo" + "github.com/microsoft/retina/operator/cilium-crds/config" "github.com/microsoft/retina/pkg/log" "github.com/pkg/errors" "github.com/spf13/viper" @@ -36,10 +37,11 @@ import ( var ( // set logger field: subsys=retina-operator - binaryName = filepath.Base(os.Args[0]) - slogLoggerOnce sync.Once - cachedSlogLogger *slog.Logger - operatorIDLength = 10 + binaryName = filepath.Base(os.Args[0]) + slogLoggerOnce sync.Once + cachedSlogLogger *slog.Logger + operatorIDLength = 10 + errLeaderElectionNamespaceRequired = errors.New("--leader-election-namespace must be set") ) // slogLogger returns a zap-backed slog logger. Resolved lazily so that @@ -64,13 +66,19 @@ func Execute(h *hive.Hive) { func registerOperatorHooks( l *slog.Logger, lc cell.Lifecycle, llc *LeaderLifecycle, clientset k8sClient.Clientset, shutdowner hive.Shutdowner, -) { + cfg config.Config, +) error { + leaderElectionNamespace := cfg.LeaderElectionNamespace + if leaderElectionNamespace == "" { + return errLeaderElectionNamespaceRequired + } + l.Info("using namespace for leader election lease", "namespace", leaderElectionNamespace) var wg sync.WaitGroup lc.Append(cell.Hook{ OnStart: func(cell.HookContext) error { wg.Add(1) go func() { - runOperator(l, llc, clientset, shutdowner) + runOperator(l, llc, clientset, shutdowner, leaderElectionNamespace) wg.Done() }() return nil @@ -84,6 +92,7 @@ func registerOperatorHooks( return nil }, }) + return nil } func initEnv(vp *viper.Viper) { @@ -134,7 +143,7 @@ func doCleanup() { // runOperator implements the logic of leader election for cilium-operator using // built-in leader election capability in kubernetes. // See: https://github.com/kubernetes/client-go/blob/master/examples/leader-election/main.go -func runOperator(l *slog.Logger, lc *LeaderLifecycle, clientset k8sClient.Clientset, shutdowner hive.Shutdowner) { +func runOperator(l *slog.Logger, lc *LeaderLifecycle, clientset k8sClient.Clientset, shutdowner hive.Shutdowner, leaderElectionNamespace string) { isLeader.Store(false) leaderElectionCtx, leaderElectionCtxCancel = context.WithCancel(context.Background()) @@ -152,7 +161,7 @@ func runOperator(l *slog.Logger, lc *LeaderLifecycle, clientset k8sClient.Client leResourceLock, err := resourcelock.NewFromKubeconfig( resourcelock.LeasesResourceLock, - operatorK8sNamespace, + leaderElectionNamespace, leaderElectionResourceLockName, resourcelock.ResourceLockConfig{ // Identity name of the lock holder From 537c2d485eec2ab110797426fe9d989da4fe469f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 14:45:19 -0400 Subject: [PATCH 432/448] deps: bump the azurelinux-base group across 4 directories with 2 updates (#2371) Bumps the azurelinux-base group with 2 updates in the /cli directory: azurelinux/base/core and azurelinux/distroless/minimal. Bumps the azurelinux-base group with 2 updates in the /controller directory: azurelinux/base/core and azurelinux/distroless/minimal. Bumps the azurelinux-base group with 1 update in the /operator directory: azurelinux/distroless/minimal. Bumps the azurelinux-base group with 1 update in the /shell directory: azurelinux/base/core. Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/distroless/minimal` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Updates `azurelinux/base/core` from 3.0 to 3.0.20260517 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 6 +++--- controller/Dockerfile | 4 ++-- operator/Dockerfile | 2 +- shell/Dockerfile | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 95197283ec..5a2a690391 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -25,11 +25,11 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ # minimal libs stage — provides only the system libraries needed by the CGO-enabled binary, # without the bloat of the full Go SDK image (python, gcc, systemd, etc.) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS libs +FROM mcr.microsoft.com/azurelinux/base/core:3.0.20260517@sha256:f5e224c47997aa4a5d3d8addfcc3866e175e7026368a71ce1be2c0eed1876f04 AS libs # Target 1: Distroless (secure, minimal) # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS distroless-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0.20260517@sha256:0c64ab9cfc44d4f100c0590bd59ead9afedda6cc54f14bb7465b5f9c35ddc037 AS distroless-target COPY --from=libs /lib/ /lib COPY --from=libs /usr/lib/ /usr/lib COPY --from=libs /etc/pki/tls/ /etc/pki/tls/ @@ -38,7 +38,7 @@ COPY --from=builder /workspace/kubectl-retina . # Target 2: Shell-enabled (operational, init container support) # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:35149ae8dd179684f969944f54a337c665a64e702486154eb44253fb39c2505b AS shell-target +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/base/core:3.0.20260517@sha256:f5e224c47997aa4a5d3d8addfcc3866e175e7026368a71ce1be2c0eed1876f04 AS shell-target WORKDIR / COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina RUN chmod +x /bin/kubectl-retina diff --git a/controller/Dockerfile b/controller/Dockerfile index cf772095ad..4432fd3d7f 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -4,10 +4,10 @@ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:9230290079612a2a8d30a0aa8b8f097c3194e787d09987df0c3e6b8f6271ee27 AS azurelinux-core +FROM mcr.microsoft.com/azurelinux/base/core:3.0.20260517@sha256:f5e224c47997aa4a5d3d8addfcc3866e175e7026368a71ce1be2c0eed1876f04 AS azurelinux-core # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:5a66f9f16ac675db2a8229dac72d83811b73b502d6ad192d8b374c7f3be498af AS azurelinux-distroless +FROM mcr.microsoft.com/azurelinux/distroless/minimal:3.0.20260517@sha256:0c64ab9cfc44d4f100c0590bd59ead9afedda6cc54f14bb7465b5f9c35ddc037 AS azurelinux-distroless # build stages diff --git a/operator/Dockerfile b/operator/Dockerfile index 0ea338d518..50be5d4e90 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -25,7 +25,7 @@ RUN --mount=type=cache,target="/root/.cache/go-build" \ ##################### controller ####################### # skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0@sha256:4c30ebfa41297a79e98dc08117cc17e80245aacff9dfd0578cbc8c75c2368566 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal:3.0.20260517@sha256:0c64ab9cfc44d4f100c0590bd59ead9afedda6cc54f14bb7465b5f9c35ddc037 WORKDIR / COPY --from=builder /lib /lib COPY --from=builder /usr/lib/ /usr/lib diff --git a/shell/Dockerfile b/shell/Dockerfile index aa6f70d433..370bbba478 100644 --- a/shell/Dockerfile +++ b/shell/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/azurelinux/base/core:3.0@sha256:82e37ddcf271af1b720036697d8ab8c95f7001c3eaf7694a9ca17b35d84085de +FROM mcr.microsoft.com/azurelinux/base/core:3.0.20260517@sha256:f5e224c47997aa4a5d3d8addfcc3866e175e7026368a71ce1be2c0eed1876f04 RUN tdnf install -y \ bind-utils \ From 664b15505f6303a27cf2c643e23f549e0fd6f1f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 19:14:28 -0400 Subject: [PATCH 433/448] deps: bump github.com/containerd/containerd from 1.7.30 to 1.7.32 (#2372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.30 to 1.7.32.
Release notes

Sourced from github.com/containerd/containerd's releases.

containerd 1.7.32

Welcome to the v1.7.32 release of containerd!


The thirty-second patch release for containerd 1.7 contains various fixes and updates including a security patch.

  • containerd

  • Allow hosts.toml to contain only root-level fields without an explicit [host] section (#10028)

  • Fix handling of out-of-range USER values in OCI spec to avoid unexpected username/group lookups (#13450)

  • Apply hardening to block AF_ALG in default socket policy (#13406)

  • Support both "volatile" and "fsync=volatile" mount options for volatile snapshotter (#13299)

  • Set AppArmor abi conditionally to support versions < 3.0 (#13273)

Please try out the release binaries and report any issues at https://github.com/containerd/containerd/issues.

  • Maksym Pavlenko
  • Chris Henzie
  • Derek McGowan
  • Paweł Gronowski
  • Samuel Karp
  • Wei Fu
  • Brad Davidson
  • Brian Goff
  • LEI WANG
  • Phil Estes
  • bc87d865c Prepare release notes for v1.7.32
  • oci: return explicit error for out-of-range USER values (#13450)
    • 503f47946 oci: return explicit error for out-of-range USER values
  • seccomp: Block AF_ALG in default socket policy (#13406)
    • e55b747d3 seccomp: Block AF_ALG in default socket policy
    • 4627a65f8 seccomp: Document socket rule scope and socketcall limitation
  • Fix issue with empty host tree in hosts.toml (#10028)
    • 24007441d Fix error parsing hosts.toml without any host tree
  • Support both styles of volatile mount option (#13299)
    • 940733149 Support both styles of volatile mount option
  • apparmor: Set abi conditionally (#13273)
  • Add GitHub Action for k8s node e2e tests (#13258)
    • 0db1e143a Add GitHub Action for k8s node e2e tests
  • Update release process after 1.7 (#13236)
    • 3223a75c2 Update for latest updates to release tool

... (truncated)

Commits
  • 180a7b7 Merge pull request #13452 from samuelkarp/prepare-1.7.32
  • bc87d86 Prepare release notes for v1.7.32
  • 6a05ddd Merge pull request #13450 from samuelkarp/oci-withuser-errrange-1.7
  • 9c3d01b Merge pull request #13406 from k8s-infra-cherrypick-robot/cherry-pick-13327-t...
  • e55b747 seccomp: Block AF_ALG in default socket policy
  • 4627a65 seccomp: Document socket rule scope and socketcall limitation
  • 33d9e24 Merge pull request #10028 from brandond/fix-hosts-toml
  • 503f479 oci: return explicit error for out-of-range USER values
  • 4393e22 Merge pull request #13299 from chrishenzie/release/1.7-volatile
  • 9407331 Support both styles of volatile mount option
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/containerd/containerd&package-manager=go_modules&previous-version=1.7.30&new-version=1.7.32)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e4139242f0..e496b97280 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/cilium/stream v0.0.1 // indirect github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect - github.com/containerd/containerd v1.7.30 // indirect + github.com/containerd/containerd v1.7.32 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect diff --git a/go.sum b/go.sum index e4c0ae6a5d..11edad6bd2 100644 --- a/go.sum +++ b/go.sum @@ -436,8 +436,8 @@ github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUo github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= -github.com/containerd/containerd v1.7.30 h1:/2vezDpLDVGGmkUXmlNPLCCNKHJ5BbC5tJB5JNzQhqE= -github.com/containerd/containerd v1.7.30/go.mod h1:fek494vwJClULlTpExsmOyKCMUAbuVjlFsJQc4/j44M= +github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= +github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= 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= From 247e8867c02dfe3a00edda89ea69f23c9a63189e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 11:35:52 -0400 Subject: [PATCH 434/448] deps: bump github.com/gopacket/gopacket from 1.5.0 to 1.6.0 (#2374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/gopacket/gopacket](https://github.com/gopacket/gopacket) from 1.5.0 to 1.6.0.
Release notes

Sourced from github.com/gopacket/gopacket's releases.

v1.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/gopacket/gopacket/compare/v1.5.0...v1.6.0

Commits
  • 95d1ae3 gre: add bounds checking (#154)
  • 7d7d998 feat: apple pktapv1 support (#153)
  • 600bed8 ip6defrag: implements an IPv6 defragmenter (#151)
  • f64f2a0 fix(lcm): add bounds check around fingerprint (#152)
  • 8c51e31 Differentiate between expected and unexpected EOFs in NgReader (#150)
  • 67ec1c7 fix(geneve): clear Options slice to prevent indefinite growth on reuse (#146)
  • 9a7f352 Industrial Protocols Round 2: Modbus, EN/IP, CIP (#142)
  • dd6e32d Added MPTCP option length check (#145)
  • ad573f1 Bump actions/checkout from 5 to 6 (#144)
  • fe11a24 Diameter protocol parsing support (#140)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/gopacket/gopacket&package-manager=go_modules&previous-version=1.5.0&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e496b97280..fbd3e2d532 100644 --- a/go.mod +++ b/go.mod @@ -236,7 +236,7 @@ require ( github.com/florianl/go-tc v0.4.8 github.com/go-logr/zapr v1.3.0 github.com/google/gopacket v1.1.19 - github.com/gopacket/gopacket v1.5.0 + github.com/gopacket/gopacket v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 diff --git a/go.sum b/go.sum index 11edad6bd2..da133d7c9d 100644 --- a/go.sum +++ b/go.sum @@ -856,8 +856,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480 github.com/googleapis/gax-go/v2 v2.19.0 h1:fYQaUOiGwll0cGj7jmHT/0nPlcrZDFPrZRhTsoCr8hE= github.com/googleapis/gax-go/v2 v2.19.0/go.mod h1:w2ROXVdfGEVFXzmlciUU4EdjHgWvB5h2n6x/8XSTTJA= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= -github.com/gopacket/gopacket v1.5.0 h1:9s9fcSUVKFlRV97B77Bq9XNV3ly2gvvsneFMQUGjc+M= -github.com/gopacket/gopacket v1.5.0/go.mod h1:i3NaGaqfoWKAr1+g7qxEdWsmfT+MXuWkAe9+THv8LME= +github.com/gopacket/gopacket v1.6.0 h1:+DdqJ4EE1C4Jx2VMDUcKvsTGc4qki2LSs0ws51RgU3Y= +github.com/gopacket/gopacket v1.6.0/go.mod h1:i3NaGaqfoWKAr1+g7qxEdWsmfT+MXuWkAe9+THv8LME= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= From ce8518cb6467dffd91018722cb3ccc1bffa9dd77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 11:36:10 -0400 Subject: [PATCH 435/448] deps: bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.6.4 to 1.7.0 (#2375) Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.6.4 to 1.7.0.
Release notes

Sourced from github.com/Azure/azure-sdk-for-go/sdk/storage/azblob's releases.

sdk/storage/azblob/v1.7.0

1.7.0 (2026-05-14)

Features Added

  • Includes all features from 1.7.0-beta.1

sdk/storage/azblob/v1.7.0-beta.1

1.7.0-beta.1 (2026-04-23)

Features Added

  • Added support for service version 2026-04-06.
  • Added support for Delete Blob Conditional Tier.
  • Added support for Server-side Encryption Rekeying.
  • Added cross-tenant support for Principal-Bound User Delegation SAS.
  • Added support for Dynamic User Delegation SAS.

Bugs Fixed

  • Added support for error code IncrementalCopyOfEarlierSnapshotNotAllowed. This replaces IncrementalCopyOfEralierVersionSnapshotNotAllowed which has been deprecated.
  • Added support for missing SKU name values.

sdk/storage/azfile/v1.7.0-beta.1

1.7.0-beta.1 (2026-05-05)

Features Added

  • Added support for service version 2026-06-06.
  • Added support for uploading up to 4 MiB of data with Create File API.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/Azure/azure-sdk-for-go/sdk/storage/azblob&package-manager=go_modules&previous-version=1.6.4&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index fbd3e2d532..4d2a223806 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 // indirect github.com/BurntSushi/toml v1.6.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -100,7 +100,7 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/golang-jwt/jwt/v5 v5.3.0 // indirect + github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.7.0 // indirect @@ -221,7 +221,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.7.0 github.com/Microsoft/hcsshim v0.14.1 github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.17 diff --git a/go.sum b/go.sum index da133d7c9d..760b3e874d 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 h1:jWQK1GI+LeGGUKBADtcH2rRqPxYB1Ljwms5gFA2LqrM= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4/go.mod h1:8mwH4klAm9DUgR2EEHyEEAQlRDvLPyg5fQry3y+cDew= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.7.0 h1:BM85pSYlVYQHdq00nxyPoOkyLF5NArJG3bOsrmbwr4k= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.7.0/go.mod h1:QYjP2cB7ZYtS/8jAbE0VSBZde/tjExqGjp+8JY6/+ts= 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/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -160,8 +160,8 @@ github.com/Azure/perf-tests/network/benchmarks/netperf v0.0.0-20241008140716-395 github.com/Azure/perf-tests/network/benchmarks/netperf v0.0.0-20241008140716-395a79947d2c/go.mod h1:jeV6A8q9uDVDwffTt5KBk+5g7bXfpEImYW6qLKn0E+I= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= -github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 h1:RHK7bS+HQMslb1sZpAokUt+zTVmue0hKSs2C791hhzU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= @@ -745,8 +745,8 @@ github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= From bd281dbf8da6755ab02df881f0149abf8e334fa9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 23 May 2026 13:13:54 -0400 Subject: [PATCH 436/448] deps: bump qs from 6.15.1 to 6.15.2 in /site (#2376) Bumps [qs](https://github.com/ljharb/qs) from 6.15.1 to 6.15.2.
Changelog

Sourced from qs's changelog.

6.15.2

  • [Fix] stringify: skip null/undefined entries in arrayFormat: 'comma' + encodeValuesOnly instead of crashing in encoder
  • [Fix] stringify: use configured delimiter after charsetSentinel (#555)
  • [Fix] stringify: apply formatter to encoded key under strictNullHandling (#554)
  • [Fix] stringify: skip null/undefined filter-array entries instead of crashing in encoder (#551)
  • [Fix] parse: handle nested bracket groups and add regression tests (#530)
  • [readme] fix grammar (#550)
  • [Dev Deps] update @ljharb/eslint-config
  • [Tests] add regression tests for keys containing percent-encoded bracket text
Commits
  • 9aca407 v6.15.2
  • 5e33d33 [Dev Deps] update @ljharb/eslint-config
  • 21f80b3 [Fix] stringify: skip null/undefined entries in arrayFormat: 'comma' + `e...
  • a0a81ea [Fix] stringify: use configured delimiter after charsetSentinel
  • e3062f7 [Fix] stringify: apply formatter to encoded key under strictNullHandling
  • 0c180a4 [Fix] stringify: skip null/undefined filter-array entries instead of crashi...
  • 3a8b94a [Tests] add regression tests for keys containing percent-encoded bracket text
  • 96755ab [readme] fix grammar
  • a419ce5 [Fix] parse: handle nested bracket groups and add regression tests
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=qs&package-manager=npm_and_yarn&previous-version=6.15.1&new-version=6.15.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/retina/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index b7b356c0ff..5edb48b893 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -16580,9 +16580,9 @@ } }, "node_modules/qs": { - "version": "6.15.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", - "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" From 9477292925272f8fc794ff47b080fca74a7f30cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 17:49:06 -0400 Subject: [PATCH 437/448] deps: bump docker/build-push-action from 7.1.0 to 7.2.0 (#2383) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 7.1.0 to 7.2.0.
Release notes

Sourced from docker/build-push-action's releases.

v7.2.0

Full Changelog: https://github.com/docker/build-push-action/compare/v7.1.0...v7.2.0

Commits
  • f9f3042 Merge pull request #1517 from docker/dependabot/npm_and_yarn/docker/actions-t...
  • 812d5fd chore: update generated content
  • b6f6693 chore(deps): Bump @​docker/actions-toolkit from 0.87.0 to 0.90.0
  • c1c626e Merge pull request #1525 from docker/dependabot/npm_and_yarn/actions/core-3.0.1
  • 51bb284 chore: update generated content
  • 5f7884d chore(deps): Bump @​actions/core from 3.0.0 to 3.0.1
  • e01deff Merge pull request #1521 from docker/dependabot/npm_and_yarn/fast-xml-parser-...
  • 3804d49 chore: update generated content
  • 71e8947 chore(deps): Bump fast-xml-parser from 5.5.7 to 5.8.0
  • 4925ad2 Merge pull request #1526 from docker/dependabot/npm_and_yarn/postcss-8.5.10
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/build-push-action&package-manager=github_actions&previous-version=7.1.0&new-version=7.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/kapinger.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index 6d6a1710fb..ea335aea18 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -52,7 +52,7 @@ jobs: run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - name: Build Linux Kapinger Image - uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -73,7 +73,7 @@ jobs: - name: Push Linux Kapinger Image if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) - uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -103,7 +103,7 @@ jobs: run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - name: Build Windows Kapinger Image - uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: hack/tools/kapinger file: hack/tools/kapinger/Dockerfile @@ -166,7 +166,7 @@ jobs: run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - name: Build Linux Toolbox Image - uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: hack/tools file: hack/tools/toolbox/Dockerfile From d9b249e5bd368e194bdf7356aac10119a55cb6fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 21:49:42 +0000 Subject: [PATCH 438/448] deps: bump github.com/onsi/gomega from 1.40.0 to 1.41.0 (#2377) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.40.0 to 1.41.0.
Changelog

Sourced from github.com/onsi/gomega's changelog.

1.41.0

Features

Add BeASlice and BeAnArray matchers

Fixes

Object formatting now detects pointer cycles to avoid runaway formatting output.

Commits
  • af2bccb v1.41.0
  • 73e81f6 v1.41.0 (full)
  • e35a84f feat: devcontainer configuration with local pkgsite and GH pages
  • f12e5e1 fix(format): detect pointer cycles to avoid runaway formatting output
  • e14831f Add optionalDescription docs to AsyncAssertion and Assertion interfaces
  • 344b94d Add BeASlice and BeAnArray matchers
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/onsi/gomega&package-manager=go_modules&previous-version=1.40.0&new-version=1.41.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4d2a223806..8cd8dcbbae 100644 --- a/go.mod +++ b/go.mod @@ -244,7 +244,7 @@ require ( github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c github.com/onsi/ginkgo/v2 v2.28.3 - github.com/onsi/gomega v1.40.0 + github.com/onsi/gomega v1.41.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.67.5 diff --git a/go.sum b/go.sum index 760b3e874d..46ca623a55 100644 --- a/go.sum +++ b/go.sum @@ -1261,8 +1261,8 @@ github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc= -github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= +github.com/onsi/gomega v1.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA= +github.com/onsi/gomega v1.41.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= 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= From 0c889d42d836b89ff3798777b8a1e0968305f9c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 17:50:03 -0400 Subject: [PATCH 439/448] deps: bump actions/stale from 10.2.0 to 10.3.0 (#2382) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 10.2.0 to 10.3.0.
Release notes

Sourced from actions/stale's releases.

v10.3.0

What's Changed

Bug Fix

Dependency Updates

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v10...v10.3.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=10.2.0&new-version=10.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index f52cfed687..f70e5acc90 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -13,7 +13,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 + - uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0 id: stale with: ascending: true From 93ce300796271524897bbfa5425d1517343099fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 21:51:14 +0000 Subject: [PATCH 440/448] deps: bump github/codeql-action from 4.35.5 to 4.36.0 (#2380) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.5 to 4.36.0.
Release notes

Sourced from github/codeql-action's releases.

v4.36.0

  • Breaking change: Bump the minimum required CodeQL bundle version to 2.19.4. #3894
  • Add support for SHA-256 Git object IDs. #3893
  • Update default CodeQL bundle version to 2.25.5. #3926
Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.36.0 - 22 May 2026

  • Breaking change: Bump the minimum required CodeQL bundle version to 2.19.4. #3894
  • Add support for SHA-256 Git object IDs. #3893
  • Update default CodeQL bundle version to 2.25.5. #3926

4.35.5 - 15 May 2026

  • We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. #3899
  • For performance and accuracy reasons, improved incremental analysis will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. #3791
  • If multiple inputs are provided for the GitHub-internal analysis-kinds input, only code-scanning will be enabled. The analysis-kinds input is experimental, for GitHub-internal use only, and may change without notice at any time. #3892
  • Added an experimental change which, when running a Code Scanning analysis for a PR with improved incremental analysis enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. #3880

4.35.4 - 07 May 2026

  • Update default CodeQL bundle version to 2.25.4. #3881

4.35.3 - 01 May 2026

  • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. #3837
  • Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. #3850
  • Best-effort connection tests for private registries now use GET requests instead of HEAD for better compatibility with various registry implementations. For NuGet feeds, the test is now always performed against the service index. #3853
  • Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. #3852
  • Update default CodeQL bundle version to 2.25.3. #3865

4.35.2 - 15 Apr 2026

  • The undocumented TRAP cache cleanup feature that could be enabled using the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the trap-caching: false input to the init Action. #3795
  • The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. #3789
  • Python analysis on GHES no longer extracts the standard library, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. #3794
  • Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. #3807
  • Update default CodeQL bundle version to 2.25.2. #3823

4.35.1 - 27 Mar 2026

4.35.0 - 27 Mar 2026

... (truncated)

Commits
  • 7211b7c Merge pull request #3927 from github/update-v4.36.0-ebc2d9e2b
  • 7740f2f Update changelog for v4.36.0
  • ebc2d9e Merge pull request #3926 from github/update-bundle/codeql-bundle-v2.25.5
  • d1f74b7 Add changelog note
  • 2dc40ce Update default bundle to codeql-bundle-v2.25.5
  • 8449852 Merge pull request #3910 from github/henrymercer/repo-size-diff-check
  • 72ac23c Update excluded required check list
  • c5297a2 Merge pull request #3919 from github/henrymercer/workflow-concurrency
  • 8ffeae7 CI: Automatically cancel non-generated workflows
  • f3f52bf Revert getErrorMessage import
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.35.5&new-version=4.36.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 6 +++--- .github/workflows/trivy.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index efe333ec31..519a76ca9e 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -40,12 +40,12 @@ jobs: with: go-version-file: go.mod - name: Initialize CodeQL - uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index c4403df694..c9df0bbc9f 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -48,6 +48,6 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: sarif_file: "trivy-results.sarif" From 287d8b7e8f28f7bfe9028532fe9ffee9337206d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 21:51:55 +0000 Subject: [PATCH 441/448] deps: bump github.com/mdlayher/netlink from 1.11.1 to 1.11.2 (#2378) Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.11.1 to 1.11.2.
Release notes

Sourced from github.com/mdlayher/netlink's releases.

v1.11.2

See https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md#v1112

Changelog

Sourced from github.com/mdlayher/netlink's changelog.

v1.11.2

  • [Bug Fix]: #291 fixed a bug where netlink.Conn.Receive would block concurrent calls to netlink.Conn.Send when blocking in recvmsg.
  • [Improvement]: #289 updated golang.org/x/net and golang.org/x/sys dependencies.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/mdlayher/netlink&package-manager=go_modules&previous-version=1.11.1&new-version=1.11.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8cd8dcbbae..cb27df068a 100644 --- a/go.mod +++ b/go.mod @@ -240,7 +240,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/jellydator/ttlcache/v3 v3.4.0 github.com/jsternberg/zap-logfmt v1.3.0 - github.com/mdlayher/netlink v1.11.1 + github.com/mdlayher/netlink v1.11.2 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c github.com/onsi/ginkgo/v2 v2.28.3 diff --git a/go.sum b/go.sum index 46ca623a55..7fa0c45176 100644 --- a/go.sum +++ b/go.sum @@ -1149,8 +1149,8 @@ github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuri github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= github.com/mdlayher/netlink v1.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU= -github.com/mdlayher/netlink v1.11.1 h1:T136gDS6Gkt+hLncaBwKdW5GpEC8Z0ykqimOebVoal0= -github.com/mdlayher/netlink v1.11.1/go.mod h1:ao4LjamyK4Uq9L8+fQzqFYpAncbeCdwbvd9Edv/pYnc= +github.com/mdlayher/netlink v1.11.2 h1:HKh2jqe+omdSWcQ88nrT7INE61B0NXfiSPFdgL4YbNI= +github.com/mdlayher/netlink v1.11.2/go.mod h1:uT2Yc/QLaZubzDpZIBi9d4GoeLwtp3x1AMeqSRrK2sA= github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= github.com/mdlayher/socket v0.6.0 h1:ScZPaAGyO1icQnbFrhPM8mnXyMu9qukC1K4ZoM2IQKU= From 60d1cd8d550c4af52363cef277eb63efe4d49b17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 18:45:31 -0400 Subject: [PATCH 442/448] deps: bump docker/setup-buildx-action from 4.0.0 to 4.1.0 (#2381) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 4.0.0 to 4.1.0.
Release notes

Sourced from docker/setup-buildx-action's releases.

v4.1.0

Full Changelog: https://github.com/docker/setup-buildx-action/compare/v4.0.0...v4.1.0

Commits
  • d7f5e7f Merge pull request #489 from docker/dependabot/npm_and_yarn/docker/actions-to...
  • 92bc5c9 chore: update generated content
  • da11e35 build(deps): bump @​docker/actions-toolkit from 0.79.0 to 0.90.0
  • f021e16 Merge pull request #492 from docker/dependabot/npm_and_yarn/undici-6.24.1
  • b5af94f chore: update generated content
  • 16ad977 build(deps): bump undici from 6.23.0 to 6.25.0
  • d7a12d7 Merge pull request #495 from docker/dependabot/npm_and_yarn/glob-10.5.0
  • 28ff27d build(deps): bump glob from 10.3.12 to 13.0.6
  • daf436b Merge pull request #496 from docker/dependabot/npm_and_yarn/fast-xml-parser-5...
  • 9725348 chore: update generated content
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/setup-buildx-action&package-manager=github_actions&previous-version=4.0.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/kapinger.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/kapinger.yaml b/.github/workflows/kapinger.yaml index ea335aea18..ad9fff855f 100644 --- a/.github/workflows/kapinger.yaml +++ b/.github/workflows/kapinger.yaml @@ -45,7 +45,7 @@ jobs: run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Log in to GHCR if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) @@ -96,7 +96,7 @@ jobs: run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Log in to GHCR if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) @@ -128,7 +128,7 @@ jobs: run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Log in to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin @@ -159,7 +159,7 @@ jobs: run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Log in to GHCR if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) From 27f1a7fdadfcbaa610680b5c841ec281040f5fea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 19:56:57 -0400 Subject: [PATCH 443/448] deps: bump github.com/onsi/ginkgo/v2 from 2.28.3 to 2.29.0 (#2379) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.28.3 to 2.29.0.
Release notes

Sourced from github.com/onsi/ginkgo/v2's releases.

v2.29.0

2.29.0

GinkgoHelperGo makes it easier to write test helpers that need to run in goroutines. Specifically, it makes managing the failure state and capturing failure panics correctly straightforward.

ginkgo outline now includes entries defined in DescribeTableSubtree

Changelog

Sourced from github.com/onsi/ginkgo/v2's changelog.

2.29.0

GinkgoHelperGo makes it easier to write test helpers that need to run in goroutines. Specifically, it makes managing the failure state and capturing failure panics correctly straightforward.

ginkgo outline now includes entries defined in DescribeTableSubtree

Commits
  • 04b5bcb v2.29.0
  • 124232a docs: GinkgoHelperGo
  • ad9cee8 feat: GinkgoHelperGo, with integration tests
  • 9e56a0a chore: refactor devcontainer for better maintenance
  • 3d235a9 chore: ignore internal/tmp_*/ integration suite temporary dirs
  • 782666a feat: devcontainer configuration with local pkgsite and GH pages
  • 009dd04 Support DescribeTableSubtree in ginkgo outline
  • See full diff in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cb27df068a..93545089e1 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( github.com/mdlayher/netlink v1.11.2 github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c - github.com/onsi/ginkgo/v2 v2.28.3 + github.com/onsi/ginkgo/v2 v2.29.0 github.com/onsi/gomega v1.41.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_model v0.6.2 diff --git a/go.sum b/go.sum index 7fa0c45176..88f78d035a 100644 --- a/go.sum +++ b/go.sum @@ -1256,8 +1256,8 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.28.3 h1:4JvMdwtFU0imd8fHx25OJXoDMRexnf8v5NHKYSTTji4= -github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= +github.com/onsi/ginkgo/v2 v2.29.0 h1:rfh+ZFjgJhYWRoIqVf3Uwx/W20yLrcrE2h2GmYVRaag= +github.com/onsi/ginkgo/v2 v2.29.0/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= From d2165acd1c157eaa0b48e730c8f655166e67a943 Mon Sep 17 00:00:00 2001 From: Mereta Date: Tue, 26 May 2026 15:35:20 +0100 Subject: [PATCH 444/448] fix(capture): Fix Windows capture stop ctx. (#2385) # Description Fix Windows capture ctx. Stop Network capture parent ctx is expired by the time `stopNetworkCapture` is called. Please provide a brief description of the changes made in this pull request. ## Related Issue #2298 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed image image ## Additional Notes Issue introduced: #2322 https://github.com/microsoft/retina/pull/2322/changes#diff-bd1c3510276019b2f8f85384d4963e4fa366a428acad36280432a841079a9bf2 --------- Signed-off-by: mereta --- pkg/capture/provider/network_capture_win.go | 14 +++++-- .../provider/network_capture_win_test.go | 40 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/pkg/capture/provider/network_capture_win.go b/pkg/capture/provider/network_capture_win.go index 9163f8c734..c11ef3393d 100644 --- a/pkg/capture/provider/network_capture_win.go +++ b/pkg/capture/provider/network_capture_win.go @@ -84,7 +84,7 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil } if stopTrace { ncp.l.Info("Stopping netsh trace session before starting a new one") - _ = ncp.stopNetworkCapture(ctx) + _ = ncp.stopNetworkCapture() //nolint:contextcheck // stopNetworkCapture creates its own context } captureFileName := ncp.Filename.String() + ".etl" @@ -164,7 +164,8 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(ctx context.Context, fil } ncp.l.Info("Stop netsh") - if err := ncp.stopNetworkCapture(ctx); err != nil { + // stopNetworkCapture creates its own context; parent ctx is expired here + if err := ncp.stopNetworkCapture(); err != nil { //nolint:contextcheck // stopNetworkCapture creates its own context ncp.l.Error("Failed to stop netsh trace by 'netsh trace stop', will kill the process", zap.Error(err)) _ = captureStartCmd.Process.Kill() return fmt.Errorf("netsh stop failed: Output: %s", err) @@ -204,10 +205,15 @@ func (ncp *NetworkCaptureProvider) needToStopTraceSession(ctx context.Context) ( return false, fmt.Errorf("cannot stop trace session because it's not created by Retina capture") } -func (ncp *NetworkCaptureProvider) stopNetworkCapture(ctx context.Context) error { +func (ncp *NetworkCaptureProvider) stopNetworkCapture() error { ncp.l.Info("Stopping netsh trace session") - command := exec.CommandContext(ctx, "netsh", "trace", "stop") + // Create independent context for cleanup. + // netsh trace stop completes in ~1s; 30s timeout provides ample safety margin. + stopCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + command := exec.CommandContext(stopCtx, "netsh", "trace", "stop") output, err := command.CombinedOutput() // ignore the error when stop the trace when no live trace session exists. if strings.Contains(string(output), "There is no trace session currently in progress") { diff --git a/pkg/capture/provider/network_capture_win_test.go b/pkg/capture/provider/network_capture_win_test.go index 87e3a03fa4..5e51d45a7a 100644 --- a/pkg/capture/provider/network_capture_win_test.go +++ b/pkg/capture/provider/network_capture_win_test.go @@ -6,7 +6,13 @@ package provider import ( + "context" "testing" + "time" + + "github.com/microsoft/retina/pkg/capture/file" + "github.com/microsoft/retina/pkg/log" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestValidateNetshFilter(t *testing.T) { @@ -114,3 +120,37 @@ func TestValidateNetshFilter(t *testing.T) { }) } } + +// TestStopNetworkCapture_ContextIndependence verifies stopNetworkCapture creates its own context +func TestStopNetworkCapture_ContextIndependence(t *testing.T) { + now := metav1.Now() + ncp := &NetworkCaptureProvider{ + NetworkCaptureProviderCommon: NetworkCaptureProviderCommon{ + TmpCaptureDir: t.TempDir(), + l: log.Logger().Named("test-capture"), + }, + Filename: file.CaptureFilename{ + CaptureName: "test-capture", + NodeHostname: "test-node", + StartTimestamp: &now, + }, + } + + // Create an expired context (simulating capture duration ending) + parentCtx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond) + time.Sleep(10 * time.Millisecond) + defer cancel() + + if parentCtx.Err() == nil { + t.Fatal("Setup error: parent context should be expired") + } + + // Call StopNetworkCapture - should NOT return "context deadline exceeded" + err := ncp.stopNetworkCapture() + + if err != nil && err.Error() == "context deadline exceeded" { + t.Fatal("StopNetworkCapture returned 'context deadline exceeded' - bug reintroduced") + } + + t.Logf("StopNetworkCapture uses independent context (netsh error expected: %v)", err) +} From c87f5b120317104326416b2cd50967bbf3460520 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 17:14:52 -0400 Subject: [PATCH 445/448] deps: bump sigs.k8s.io/cloud-provider-azure/pkg/azclient from 0.20.3 to 0.20.4 in the azure-sdk group (#2387) Bumps the azure-sdk group with 1 update: [sigs.k8s.io/cloud-provider-azure/pkg/azclient](https://github.com/kubernetes-sigs/cloud-provider-azure). Updates `sigs.k8s.io/cloud-provider-azure/pkg/azclient` from 0.20.3 to 0.20.4
Commits
  • 904c0e2 build(deps): bump the all group in /pkg/azclient with 2 updates (#10395)
  • de33aeb build(deps): bump the all group with 2 updates (#10400)
  • b46ff35 build(deps): bump the all group in /kubetest2-aks with 2 updates (#10394)
  • a3c548d fix(multi-slb): serialize backendPoolUpdater with service reconcile loop (#10...
  • ce0c4f3 fix: update generate-release-note script (#10350)
  • 593a7fd build(deps): bump oss/go/microsoft/golang in the all group (#10311)
  • 9352d6d build(deps): bump the all group across 1 directory with 5 updates (#10379)
  • 5022220 build(deps): bump the all group across 1 directory with 8 updates (#10313)
  • 37264c3 docs: split agent guide into references (#10374)
  • 11093ba docs: document Dependabot rebase handling (#10369)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/cloud-provider-azure/pkg/azclient&package-manager=go_modules&previous-version=0.20.3&new-version=0.20.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 93545089e1..f188d44f3f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.10.2 go.uber.org/zap v1.28.0 k8s.io/client-go v0.35.4 - sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.3 + sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.4 sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 ) diff --git a/go.sum b/go.sum index 88f78d035a..e684ca9600 100644 --- a/go.sum +++ b/go.sum @@ -2027,8 +2027,8 @@ oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.3 h1:Dil9+oiwQPA7odxzOvdconusdXU7ZNRKZvwO70q8V30= -sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.3/go.mod h1:YnLuHCYfiPHR3QgWM8dXJk/hYC4pLr2mOOVyJsYqTYQ= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.4 h1:UOxIkkOqrkrucdVW+N0ZyDUPL+7eZHPeJ9KYw2FXkDQ= +sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.20.4/go.mod h1:qLMV2RATHSfIH8DhLRdvCxYdPDwLUgAAx4iDrMRvLRg= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0 h1:yjbZWgLUgTnLCGxM8I88l88WgvLRIOcOmAEbacFVLnU= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.14.0/go.mod h1:6NYpRYlC7AyQaDtOQsF62plL1gDQqJwgQUwTdjp8qlU= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= From df426895154f77bd76bf6a83f0311ed9b1493dc8 Mon Sep 17 00:00:00 2001 From: Beegii Khurelsukh <72892628+BeegiiK@users.noreply.github.com> Date: Wed, 27 May 2026 10:18:09 +0100 Subject: [PATCH 446/448] feat: Adding new standard control plane dashboards for windowsebpf plugin (#2386) # Description ### Drops Analysis Dashboard 1. Focused view for identifying and troubleshooting packet drops 2. Includes drop rate analysis by reason, direction, pod, and namespace 3. Features stat tiles for at-a-glance metrics and detailed visualizations (heatmaps, pie charts, correlation charts) ### Overview Dashboard 1. High-level operational view with 6 key metric stat tiles 2. Displays total forward traffic (packets/bytes), drops, drop percentage, and active resources 3. Top 10 pod analysis for incoming/outgoing traffic 4. TCP flags distribution and traffic heatmaps for pattern identification ### Namespace Deep Dive Dashboard 1. Detailed pod-level analysis scoped to specific namespaces 2. Pod traffic summary with sparklines and gauges 3. Workload type breakdown (DaemonSet, Deployment, etc.) 4. Direction-based traffic analysis with comprehensive heatmaps ### Screenshots (if applicable) or Testing Completed image ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .../windows-ebpf-drops-dashboard.json | 1233 ++++++++++++++ .../windows-ebpf-namespace-dashboard.json | 1398 +++++++++++++++ .../windows-ebpf-overview-dashboard.json | 1517 +++++++++++++++++ 3 files changed, 4148 insertions(+) create mode 100644 deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-drops-dashboard.json create mode 100644 deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-namespace-dashboard.json create mode 100644 deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-overview-dashboard.json diff --git a/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-drops-dashboard.json b/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-drops-dashboard.json new file mode 100644 index 0000000000..04310e7e49 --- /dev/null +++ b/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-drops-dashboard.json @@ -0,0 +1,1233 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 239082, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "k8s:retina-network-observability" + ], + "targetBlank": false, + "title": "Dashboards: Retina Network Observability", + "tooltip": "", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": false, + "icon": "info", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "Documentation", + "tooltip": "", + "type": "link", + "url": "https://retina.sh/docs/Introduction/intro" + } + ], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "inverted", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"})", + "legendFormat": "Total Drops", + "range": true, + "refId": "A" + } + ], + "title": "Total Drops", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "inverted", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Drop Rate", + "range": true, + "refId": "A" + } + ], + "title": "Drop Rate (pps)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 5 + }, + { + "color": "red", + "value": 15 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "inverted", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "(sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])) / (sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])) + sum(rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])))) * 100", + "legendFormat": "Drop %", + "range": true, + "refId": "A" + } + ], + "title": "Drop Percentage", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 18, + "y": 0 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(1, sum by(reason) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])))", + "legendFormat": "{{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Top Drop Reason", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 4 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(reason) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])))", + "legendFormat": "{{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Drop Rate by Reason (Top 10)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "egress" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "ingress" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 4 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(direction) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{direction}}", + "range": true, + "refId": "A" + } + ], + "title": "Drops by Direction (Egress vs Ingress)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 7, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(podname, namespace) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\", podname!=\"\"}[$__rate_interval])))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 Pods by Drop Rate", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drop Reason Search", + "url": "https://www.bing.com/copilotsearch?q=what does ${__field.labels.reason} mean in the context of network drops" + } + ], + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 8, + "options": { + "displayLabels": [ + "percent" + ], + "legend": { + "displayMode": "table", + "placement": "right", + "showLegend": true, + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "sort": "desc", + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(reason) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])))", + "legendFormat": "{{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 Drop Reasons Distribution", + "type": "piechart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Drop Count" + }, + "properties": [ + { + "id": "unit", + "value": "pps" + }, + { + "id": "custom.axisPlacement", + "value": "left" + }, + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Drop Bytes" + }, + "properties": [ + { + "id": "unit", + "value": "Bps" + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 9, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Drop Count", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_drop_bytes{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Drop Bytes", + "range": true, + "refId": "B" + } + ], + "title": "Drop Bytes vs Count Correlation", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto", + "wrapText": false + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 50 + }, + { + "color": "red", + "value": 500 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "custom.width", + "value": 200 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Packets Per Second (pps)" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "type": "color-text", + "wrapText": false + } + }, + { + "id": "custom.width", + "value": 221 + }, + { + "id": "custom.align", + "value": "center" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Drop Rate" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "drawStyle": "line", + "gradientMode": "hue", + "hideValue": true, + "lineStyle": { + "dash": [ + 10, + 10 + ], + "fill": "solid" + }, + "type": "sparkline" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 10, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Packets Per Second (pps)" + } + ] + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(namespace) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", namespace!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{namespace}}", + "range": false, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(namespace) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", namespace!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Drops by Namespace", + "transformations": [ + { + "id": "timeSeriesTable", + "options": { + "B": { + "timeField": "Time" + } + } + }, + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "includeByName": {}, + "indexByName": {}, + "renameByName": { + "Trend #A": "Drop Rate", + "Trend #B": "Drop Rate", + "Value": "Packets Per Second (pps)", + "Value #A": "Drop Rate", + "cosmic-networking": "", + "namespace": "" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 11, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-red", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Reds", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname, namespace, cluster) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=~\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Drop Patterns Heatmap (Pod x Time)", + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 41, + "tags": [ + "k8s:retina-network-observability", + "windows-ebpf", + "drops" + ], + "templating": { + "list": [ + { + "current": { + "text": "CosmicMdmPreProd", + "value": "f48d17e6-07ac-4efc-97ad-b347b565c3f4" + }, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(networkobservability_adv_drop_count,cluster)", + "includeAll": false, + "label": "Cluster", + "name": "cluster", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(networkobservability_adv_drop_count,cluster)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(networkobservability_adv_drop_count, namespace)", + "includeAll": true, + "label": "Namespace", + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(networkobservability_adv_drop_count, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Kubernetes / Networking / Retina (Standard) / Windows eBPF Drops", + "uid": "RetinaWindowsEBPFDropsClusterWIP", + "version": 22 +} \ No newline at end of file diff --git a/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-namespace-dashboard.json b/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-namespace-dashboard.json new file mode 100644 index 0000000000..8893b0533e --- /dev/null +++ b/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-namespace-dashboard.json @@ -0,0 +1,1398 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 239083, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "k8s:retina-network-observability" + ], + "targetBlank": false, + "title": "Dashboards: Retina Network Observability", + "tooltip": "", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": false, + "icon": "info", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "Documentation", + "tooltip": "", + "type": "link", + "url": "https://retina.sh/docs/Introduction/intro" + } + ], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "titleSize": 18, + "valueSize": 28 + }, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "vector(1)", + "legendFormat": "Cluster: $cluster | Namespace: $namespace", + "range": true, + "refId": "A" + } + ], + "title": "Current Namespace Selection", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 3 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", cluster=\"$cluster\", podname!=\"\"}[$__rate_interval]))", + "legendFormat": "{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Pod-Level Forward Traffic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 3 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Pod-Level Drop Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Pod" + }, + "properties": [ + { + "id": "custom.width", + "value": 305 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Forward Rate" + }, + "properties": [ + { + "id": "unit", + "value": "pps" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "auto" + } + }, + { + "id": "custom.width", + "value": 200 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Drop Rate" + }, + "properties": [ + { + "id": "unit", + "value": "pps" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "auto" + } + }, + { + "id": "custom.width", + "value": 200 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Drop %" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 5 + }, + { + "color": "red", + "value": 15 + } + ] + } + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Forward Rate" + } + ] + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "format": "table", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "format": "table", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "(sum by(podname) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval])) / (sum by(podname) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval])) + sum by(podname) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval])))) * 100", + "format": "table", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "C" + } + ], + "title": "Pod Traffic Summary", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "includeByName": {}, + "indexByName": { + "Time": 0, + "Value #A": 2, + "Value #B": 3, + "Value #C": 4, + "podname": 1 + }, + "renameByName": { + "Value #A": "Forward Rate", + "Value #B": "Drop Rate", + "Value #C": "Drop %", + "podname": "Pod" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname, reason) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}} - {{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Drop Reasons by Pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname, flag) (rate(networkobservability_adv_tcpflags_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}} - {{flag}}", + "range": true, + "refId": "A" + } + ], + "title": "TCP Flags by Pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(workload_kind, workload_name) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", workload_name!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{workload_kind}}: {{workload_name}}", + "range": true, + "refId": "A" + } + ], + "title": "Forward Traffic by Workload Type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(workload_kind, workload_name) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", workload_name!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{workload_kind}}: {{workload_name}}", + "range": true, + "refId": "A" + } + ], + "title": "Drop Rate by Workload Type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 9, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname, direction) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\",cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}} - {{direction}}", + "range": true, + "refId": "A" + } + ], + "title": "Forward Traffic by Pod and Direction", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_forward_bytes{namespace=~\"$namespace\", podname!=\"\",cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Forward Bytes by Pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 11, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-green", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Greens", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Pod Forward Traffic Heatmap", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 12, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-red", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Reds", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname) (rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Pod Drop Rate Heatmap", + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 41, + "tags": [ + "k8s:retina-network-observability", + "windows-ebpf", + "namespace-deep-dive" + ], + "templating": { + "list": [ + { + "current": { + "text": "CosmicMdmPreProd", + "value": "f48d17e6-07ac-4efc-97ad-b347b565c3f4" + }, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(networkobservability_adv_drop_count,cluster)", + "includeAll": false, + "label": "Cluster", + "name": "cluster", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(networkobservability_adv_drop_count,cluster)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(networkobservability_adv_forward_count, namespace)", + "includeAll": false, + "label": "Namespace", + "name": "namespace", + "options": [], + "query": { + "query": "label_values(networkobservability_adv_forward_count, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Kubernetes / Networking / Retina (Standard) / Windows eBPF Namespace Deep Dive", + "uid": "RetinaWindowsEBPFNamespaceClusterWIP", + "version": 1 +} \ No newline at end of file diff --git a/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-overview-dashboard.json b/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-overview-dashboard.json new file mode 100644 index 0000000000..ce8947926e --- /dev/null +++ b/deploy/grafana-dashboards/standard-windows-ebpf/windows-ebpf-overview-dashboard.json @@ -0,0 +1,1517 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 239084, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "k8s:retina-network-observability" + ], + "targetBlank": false, + "title": "Dashboards: Retina Network Observability", + "tooltip": "", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": false, + "icon": "info", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "Documentation", + "tooltip": "", + "type": "link", + "url": "https://retina.sh/docs/Introduction/intro" + } + ], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(networkobservability_adv_forward_count{namespace=~\"$namespace\", cluster=\"$cluster\"})", + "legendFormat": "Total Forwards", + "range": true, + "refId": "A" + } + ], + "title": "Total Forward Packets", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(networkobservability_adv_forward_bytes{namespace=~\"$namespace\", cluster=\"$cluster\"})", + "legendFormat": "Total Bytes", + "range": true, + "refId": "A" + } + ], + "title": "Total Forward Bytes", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 100 + }, + { + "color": "red", + "value": 1000 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 0 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "inverted", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"})", + "legendFormat": "Total Drops", + "range": true, + "refId": "A" + } + ], + "title": "Total Drops", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 5 + }, + { + "color": "red", + "value": 15 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 0 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "inverted", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "(sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])) / (sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])) + sum(rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval])))) * 100", + "legendFormat": "Drop %", + "range": true, + "refId": "A" + } + ], + "title": "Drop Rate %", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "purple" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 16, + "y": 0 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "count(count by(podname) (networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}))", + "legendFormat": "Active Pods", + "range": true, + "refId": "A" + } + ], + "title": "Active Pods", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "count(count by(namespace) (networkobservability_adv_forward_count{namespace=~\"$namespace\", namespace!=\"\", cluster=\"$cluster\"}))", + "legendFormat": "Active Namespaces", + "range": true, + "refId": "A" + } + ], + "title": "Active Namespaces", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 4 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Total Forward Rate", + "range": true, + "refId": "A" + } + ], + "title": "Total Forward Rate (pps)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 4 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_forward_bytes{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Total Forward Bytes", + "range": true, + "refId": "A" + } + ], + "title": "Total Forward Bytes (Bps)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 9, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(podname, namespace) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\", direction=\"egress\"}[$__rate_interval])))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 Pods - Outgoing Traffic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(podname, namespace) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\", direction=\"ingress\"}[$__rate_interval])))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 Pods - Incoming Traffic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(flag) (rate(networkobservability_adv_tcpflags_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{flag}}", + "range": true, + "refId": "A" + } + ], + "title": "TCP Flags Distribution Over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 12, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-blue", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Blues", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(podname, namespace) (rate(networkobservability_adv_tcpflags_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "TCP Flags by Pod (Heatmap)", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Forwards" + }, + "properties": [ + { + "id": "unit", + "value": "pps" + }, + { + "id": "custom.axisPlacement", + "value": "left" + }, + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Drops" + }, + "properties": [ + { + "id": "unit", + "value": "pps" + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "last", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Forwards", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(networkobservability_adv_drop_count{namespace=~\"$namespace\", cluster=\"$cluster\"}[$__rate_interval]))", + "legendFormat": "Drops", + "range": true, + "refId": "B" + } + ], + "title": "Forward vs Drop Comparison", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(namespace) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", namespace!=\"\", cluster=\"$cluster\"}[$__rate_interval])))", + "legendFormat": "{{namespace}}", + "range": true, + "refId": "A" + } + ], + "title": "Namespace Traffic Breakdown (Top 10)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 15, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(podname, namespace) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\", direction=\"egress\"}[$__rate_interval])))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 Pods Outgoing Traffic (Heatmap)", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 16, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-purple", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Purples", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "11.6.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "topk(10, sum by(podname, namespace) (rate(networkobservability_adv_forward_count{namespace=~\"$namespace\", podname!=\"\", cluster=\"$cluster\", direction=\"ingress\"}[$__rate_interval])))", + "legendFormat": "{{namespace}}/{{podname}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 Pods Incoming Traffic (Heatmap)", + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 41, + "tags": [ + "k8s:retina-network-observability", + "windows-ebpf", + "overview" + ], + "templating": { + "list": [ + { + "current": { + "text": "CosmicMdmPreProd", + "value": "f48d17e6-07ac-4efc-97ad-b347b565c3f4" + }, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(networkobservability_adv_drop_count,cluster)", + "includeAll": false, + "label": "Cluster", + "name": "cluster", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(networkobservability_adv_drop_count,cluster)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(networkobservability_adv_forward_count, namespace)", + "includeAll": true, + "label": "Namespace", + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(networkobservability_adv_forward_count, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Kubernetes / Networking / Retina (Standard) / Windows eBPF Overview", + "uid": "RetinaWindowsEBPFOverviewClusterWIP", + "version": 1 +} \ No newline at end of file From 485606fe1e0c1436586837a51d920328ba3b9db6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 May 2026 12:45:40 -0400 Subject: [PATCH 447/448] deps: bump @types/react from 19.2.14 to 19.2.15 in /site (#2393) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 19.2.14 to 19.2.15.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/react&package-manager=npm_and_yarn&previous-version=19.2.14&new-version=19.2.15)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 8 ++++---- site/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 5edb48b893..6c0c7e5b2e 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -13,7 +13,7 @@ "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", - "@types/react": "^19.2.14", + "@types/react": "^19.2.15", "clsx": "^2.1.1", "docusaurus-lunr-search": "^3.6.0", "micromatch": "^4.0.8", @@ -6126,9 +6126,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "version": "19.2.15", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", + "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", "license": "MIT", "dependencies": { "csstype": "^3.2.2" diff --git a/site/package.json b/site/package.json index e72301530c..8e9a97094f 100644 --- a/site/package.json +++ b/site/package.json @@ -19,7 +19,7 @@ "@docusaurus/plugin-ideal-image": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1", "@mdx-js/react": "^3.1.1", - "@types/react": "^19.2.14", + "@types/react": "^19.2.15", "clsx": "^2.1.1", "docusaurus-lunr-search": "^3.6.0", "micromatch": "^4.0.8", From 27ef095cda05a05315f516873e8712f9ee31f8ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 May 2026 12:46:07 -0400 Subject: [PATCH 448/448] deps: bump the golang-base group across 6 directories with 1 update (#2392) Bumps the golang-base group with 1 update in the /cli directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /controller directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /hack/tools/kapinger directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /hack/tools/toolbox directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /operator directory: oss/go/microsoft/golang. Bumps the golang-base group with 1 update in the /test/image directory: oss/go/microsoft/golang. Updates `oss/go/microsoft/golang` from `75a5c75` to `ef48075` Updates `oss/go/microsoft/golang` from `75a5c75` to `ef48075` Updates `oss/go/microsoft/golang` from `e6e1c95` to `bd013a5` Updates `oss/go/microsoft/golang` from `e6e1c95` to `bd013a5` Updates `oss/go/microsoft/golang` from `75a5c75` to `ef48075` Updates `oss/go/microsoft/golang` from `75a5c75` to `ef48075` Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- controller/Dockerfile | 2 +- controller/Dockerfile.gogen | 2 +- controller/Dockerfile.proto | 2 +- controller/Dockerfile.windows-cgo | 2 +- controller/Dockerfile.windows-native | 2 +- hack/tools/kapinger/Dockerfile | 4 ++-- hack/tools/toolbox/Dockerfile | 2 +- operator/Dockerfile | 2 +- operator/Dockerfile.windows-2022 | 2 +- test/image/Dockerfile | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index 5a2a690391..784859528e 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/controller/Dockerfile b/controller/Dockerfile index 4432fd3d7f..efa36ced4b 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,7 +1,7 @@ # pinned base images # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS golang +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 AS golang # skopeo inspect docker://mcr.microsoft.com/azurelinux/base/core:3.0 --format "{{.Name}}@{{.Digest}}" FROM mcr.microsoft.com/azurelinux/base/core:3.0.20260517@sha256:f5e224c47997aa4a5d3d8addfcc3866e175e7026368a71ce1be2c0eed1876f04 AS azurelinux-core diff --git a/controller/Dockerfile.gogen b/controller/Dockerfile.gogen index a5006b691d..d0bfe348bc 100644 --- a/controller/Dockerfile.gogen +++ b/controller/Dockerfile.gogen @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 # Default linux/architecture. ARG GOOS=linux diff --git a/controller/Dockerfile.proto b/controller/Dockerfile.proto index 3be03e15fc..cc7f706d39 100644 --- a/controller/Dockerfile.proto +++ b/controller/Dockerfile.proto @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 LABEL Name=retina-builder Version=0.0.1 diff --git a/controller/Dockerfile.windows-cgo b/controller/Dockerfile.windows-cgo index 22e413b052..d5e322ba84 100644 --- a/controller/Dockerfile.windows-cgo +++ b/controller/Dockerfile.windows-cgo @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-windowsservercore-ltsc2022@sha256:6dd6f9178eb2cd736ba6da106294d934b178c6e62263845abf46e7727d47651e AS cgo +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-windowsservercore-ltsc2022@sha256:7ebc4adb9d8a8359d3d0fb6d1479962fdab5b275045e78d70e4b7cdf8f76455b AS cgo SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/controller/Dockerfile.windows-native b/controller/Dockerfile.windows-native index 54f016fd35..b62f7472ce 100644 --- a/controller/Dockerfile.windows-native +++ b/controller/Dockerfile.windows-native @@ -4,7 +4,7 @@ # Maybe one day: https://github.com/moby/buildkit/issues/616 ARG BUILDER_IMAGE # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-windowsservercore-ltsc2022 --override-os windows --format "{{.Name}}@{{.Digest}}" -FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-windowsservercore-ltsc2022@sha256:6dd6f9178eb2cd736ba6da106294d934b178c6e62263845abf46e7727d47651e AS builder +FROM --platform=windows/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-windowsservercore-ltsc2022@sha256:7ebc4adb9d8a8359d3d0fb6d1479962fdab5b275045e78d70e4b7cdf8f76455b AS builder WORKDIR C:\\retina COPY go.mod . COPY go.sum . diff --git a/hack/tools/kapinger/Dockerfile b/hack/tools/kapinger/Dockerfile index d3bcd61a0c..f6679f774d 100644 --- a/hack/tools/kapinger/Dockerfile +++ b/hack/tools/kapinger/Dockerfile @@ -1,6 +1,6 @@ # Linux builder - runs natively on the target platform (amd64 or arm64) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:e6e1c95302de09c2f0f6ea1ada9cee207d6cac9b506df5d289a29b103b0a2539 AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:bd013a5e4c7f683d44627652060269bbd4d0949143c906f6deeeda0880e72d2c AS builder WORKDIR /build ADD . . @@ -17,7 +17,7 @@ CMD ["./kapinger"] # Windows builder - cross-compiles from Linux amd64 (GOOS=windows is not affected by systemcrypto) # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:e6e1c95302de09c2f0f6ea1ada9cee207d6cac9b506df5d289a29b103b0a2539 AS windows-builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:bd013a5e4c7f683d44627652060269bbd4d0949143c906f6deeeda0880e72d2c AS windows-builder WORKDIR /build ADD . . diff --git a/hack/tools/toolbox/Dockerfile b/hack/tools/toolbox/Dockerfile index 8164c19486..e60385840e 100644 --- a/hack/tools/toolbox/Dockerfile +++ b/hack/tools/toolbox/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:e6e1c95302de09c2f0f6ea1ada9cee207d6cac9b506df5d289a29b103b0a2539 AS build +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1@sha256:bd013a5e4c7f683d44627652060269bbd4d0949143c906f6deeeda0880e72d2c AS build ADD . . WORKDIR /go/toolbox/ RUN GOOS=linux go build -o server . diff --git a/operator/Dockerfile b/operator/Dockerfile index 50be5d4e90..3415c1922c 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 AS builder ARG VERSION ARG APP_INSIGHTS_ID diff --git a/operator/Dockerfile.windows-2022 b/operator/Dockerfile.windows-2022 index e6cf417d8b..996ab5fb42 100644 --- a/operator/Dockerfile.windows-2022 +++ b/operator/Dockerfile.windows-2022 @@ -1,5 +1,5 @@ # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 AS builder # Build args ARG VERSION diff --git a/test/image/Dockerfile b/test/image/Dockerfile index 9b561c3ebc..0b2c4f699a 100644 --- a/test/image/Dockerfile +++ b/test/image/Dockerfile @@ -1,6 +1,6 @@ # build stage # skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-azurelinux3.0 --format "{{.Name}}@{{.Digest}}" -FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:75a5c75f33e2238c6a5b93167cc4a7acd96d39e217d6e370ee7adcf5c29e2a6d AS builder +FROM mcr.microsoft.com/oss/go/microsoft/golang:1.26.3-1-azurelinux3.0@sha256:ef480755a4126131197d7311ab1e24d55600407194b45349c4975b7ed0d176e6 AS builder ENV CGO_ENABLED=1 COPY . /go/src/github.com/microsoft/retina WORKDIR /go/src/github.com/microsoft/retina

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%0DRU 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μ%0C`kmw<{ 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 lTHW+`LG>aV2mbdho$$jIXuUk|6K1 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