diff --git a/common/controlmode/controlmode.go b/common/controlmode/controlmode.go index 5cab1972..1a77e98d 100644 --- a/common/controlmode/controlmode.go +++ b/common/controlmode/controlmode.go @@ -41,6 +41,8 @@ const ( HOOK KUBECTL_DIRECT KUBECTL_FAIRMQ + KUBERNETES_DIRECT + KUBERNETES_FAIRMQ ) func (cm ControlMode) String() string { @@ -57,6 +59,10 @@ func (cm ControlMode) String() string { return "kubectl_direct" case KUBECTL_FAIRMQ: return "kubectl_fairmq" + case KUBERNETES_DIRECT: + return "kubernetes_direct" + case KUBERNETES_FAIRMQ: + return "kubernetes_fairmq" } return "direct" } @@ -81,6 +87,10 @@ func (cm *ControlMode) UnmarshalText(b []byte) error { *cm = KUBECTL_DIRECT case "kubectl_fairmq": *cm = KUBECTL_FAIRMQ + case "kubernetes_direct": + *cm = KUBERNETES_DIRECT + case "kubernetes_fairmq": + *cm = KUBERNETES_FAIRMQ default: *cm = DIRECT } diff --git a/control-operator/api/v1alpha1/environment_types.go b/control-operator/api/v1alpha1/environment_types.go index 0abb6ffb..3884d658 100644 --- a/control-operator/api/v1alpha1/environment_types.go +++ b/control-operator/api/v1alpha1/environment_types.go @@ -82,7 +82,7 @@ type TaskReference struct { Name string `json:"name"` Env []v1.EnvVar `json:"env"` ArgsCLI []string `json:"argsCLI"` - ArgsTransition map[string]string `json:"argsTransition"` + ArgsTransition map[string]string `json:"argsTransition,omitempty"` } type TemplateSpecification struct { diff --git a/control-operator/config/crd/bases/aliecs.alice.cern_environments.yaml b/control-operator/config/crd/bases/aliecs.alice.cern_environments.yaml index d32e0059..4b5bed6f 100644 --- a/control-operator/config/crd/bases/aliecs.alice.cern_environments.yaml +++ b/control-operator/config/crd/bases/aliecs.alice.cern_environments.yaml @@ -4102,7 +4102,6 @@ spec: type: string required: - argsCLI - - argsTransition - env - name type: object diff --git a/control-operator/ecs-manifests/control-workflows/readout-docker.yaml b/control-operator/ecs-manifests/control-workflows/readout-docker.yaml index 043b05f7..4c7ee2cf 100644 --- a/control-operator/ecs-manifests/control-workflows/readout-docker.yaml +++ b/control-operator/ecs-manifests/control-workflows/readout-docker.yaml @@ -7,7 +7,7 @@ defaults: _module_cmdline: >- source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load Readout Control-OCCPlugin && o2-readout-exe - _plain_cmdline: "sudo -E docker run --name readout --replace --privileged --user flp -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -v /tmp:/tmp -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) --network=host --ipc=host -e O2_DETECTOR -e O2_PARTITION -e OCC_CONTROL_PORT -e O2_SYSTEM -e O2_ROLE gitlab-registry.cern.ch/aliceo2group/dockerfiles/alma9-flp-node:2 /opt/o2/bin/o2-readout-exe" + _plain_cmdline: "sudo -E docker run --name readout --replace --privileged --user flp -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -v /tmp:/tmp -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) --network=host --ipc=host -e O2_DETECTOR -e O2_PARTITION -e OCC_CONTROL_PORT -e O2_SYSTEM -e O2_ROLE gitlab-registry.cern.ch/aliceo2group/dockerfiles/alma9-flp-node/readout:1 /opt/o2/bin/o2-readout-exe" control: mode: direct wants: diff --git a/control-operator/ecs-manifests/control-workflows/readout-kube-direct.yaml b/control-operator/ecs-manifests/control-workflows/readout-kube-direct.yaml new file mode 100644 index 00000000..ca81df06 --- /dev/null +++ b/control-operator/ecs-manifests/control-workflows/readout-kube-direct.yaml @@ -0,0 +1,33 @@ +name: readout # read by workflow +defaults: + readout_cfg_uri: "consul-ini://{{ consul_endpoint }}/o2/components/readout/ANY/any/readout-standalone-{{ task_hostname }}" + user: flp + log_task_stdout: none + log_task_stderr: none + _module_cmdline: >- + source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load Readout Control-OCCPlugin && + o2-readout-exe + _plain_cmdline: "{{ o2_install_path }}/bin/o2-readout-exe" +control: + mode: kubernetes_direct +wants: + cpu: 0.15 + memory: 128 +bind: + - name: readout + type: push + rateLogging: "{{ fmq_rate_logging }}" + addressing: ipc + transport: shmem +properties: {} +command: + stdout: "{{ log_task_stdout }}" + stderr: "{{ log_task_stderr }}" + shell: true + env: + - O2_DETECTOR={{ detector }} + - O2_PARTITION={{ environment_id }} + user: "{{ user }}" + arguments: + - "{{ readout_cfg_uri }}" + value: "{{ len(modulepath)>0 ? _module_cmdline : _plain_cmdline }}" diff --git a/control-operator/ecs-manifests/control-workflows/stfbuilder-senderoutput-kube-direct.yaml b/control-operator/ecs-manifests/control-workflows/stfbuilder-senderoutput-kube-direct.yaml new file mode 100644 index 00000000..d409de28 --- /dev/null +++ b/control-operator/ecs-manifests/control-workflows/stfbuilder-senderoutput-kube-direct.yaml @@ -0,0 +1,64 @@ +name: stfbuilder-senderoutput +control: + mode: kubernetes_fairmq +defaults: + detector: TST + rdh_version: "6" + user: flp + fmq_severity: info + dd_detector_subspec: feeid + dd_discovery_endpoint: "no-op://" # location of consul docker instance + log_task_stdout: none + log_task_stderr: none + stfb_dd_mode: "physics" + stfb_fee_mask: "0xffff" + stfb_enable_datasink: "false" + stfb_datasink_dir: "/tmp" + stfb_datasink_filesize: "2048" + monitoring_dd_interval: "5" + _module_cmdline: >- + source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load DataDistribution Control-OCCPlugin && + StfBuilder + _plain_cmdline: "{{ o2_install_path }}/bin/StfBuilder" +wants: + cpu: 0.15 + memory: 128 +bind: + - name: buildertosender + type: push + rateLogging: "{{ fmq_rate_logging }}" + transport: shmem + addressing: ipc + sndBufSize: "4" +command: + env: + - O2_INFOLOGGER_MODE={{infologger_mode}} + - O2_DETECTOR={{ detector }} + - DATADIST_FEE_MASK={{ stfb_fee_mask }} + - O2_PARTITION={{ environment_id }} + stdout: "{{ log_task_stdout }}" + stderr: "{{ log_task_stderr }}" + shell: true + user: "{{ user }}" + value: "{{ len(modulepath)>0 ? _module_cmdline : _plain_cmdline }}" + arguments: + - "--session=default" + - "--transport=shmem" + - "--shm-segment-id=2" + - "--shm-segment-size=33554432" + - "--monitoring-backend={{ monitoring_dd_url }}" + - "--monitoring-process-interval={{ monitoring_dd_interval }}" + - "--discovery-partition={{ environment_id }}" + - "--discovery-endpoint={{ dd_discovery_endpoint }}" + - "--detector-rdh={{ rdh_version }}" + - "--detector-subspec={{ dd_detector_subspec }}" + - "--severity={{ fmq_severity }}" + - "--severity-infologger={{ infologger_severity }}" + - "--output-channel-name=buildertosender" + - "--shm-monitor=false" + - "--detector={{ detector }}" + - "--run-type={{ stfb_dd_mode }}" + - "{{ stfb_enable_datasink == 'true' ? '--data-sink-enable' : ' ' }}" + - "{{ stfb_enable_datasink == 'true' ? '--data-sink-dir=' + stfb_datasink_dir : ' ' }}" + - "{{ stfb_enable_datasink == 'true' ? '--data-sink-max-stfs-per-file=0' : ' ' }}" + - "{{ stfb_enable_datasink == 'true' ? '--data-sink-max-file-size=' + stfb_datasink_filesize : ' ' }}" diff --git a/control-operator/ecs-manifests/control-workflows/stfsender-kube-direct.yaml b/control-operator/ecs-manifests/control-workflows/stfsender-kube-direct.yaml new file mode 100644 index 00000000..6ed26731 --- /dev/null +++ b/control-operator/ecs-manifests/control-workflows/stfsender-kube-direct.yaml @@ -0,0 +1,68 @@ +name: stfsender +control: + mode: kubernetes_fairmq +wants: + cpu: 0.15 + memory: 128 +defaults: + max_buffered_stfs: "-1" + dd_discovery_net_if: "ib0" #the loopback intf + dd_discovery_endpoint: "no-op://" # location of consul docker instance + user: flp + fmq_severity: info + log_task_stdout: none + log_task_stderr: none + stfs_dd_region_size: 4096 + stfs_shm_segment_size: 33554432 + stfs_enable_datasink: "false" + stfs_datasink_dir: "/tmp" + stfs_datasink_filesize: "2048" + monitoring_dd_interval: "5" + _module_cmdline: >- + source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load DataDistribution Control-OCCPlugin && + numactl --cpunodebind=0 --preferred=0 -- StfSender + _plain_cmdline: "numactl" +command: + env: + - O2_INFOLOGGER_MODE={{infologger_mode}} + - http_proxy="" + - https_proxy="" + - no_proxy=-ib,.internal + - O2_DETECTOR={{ detector }} + - UCX_NET_DEVICES=mlx5_0:1 # This limits StfSender to IB interface (used as of DD v1.3.0) + - UCX_TLS=sm,self,dc,rc # Force dc/rc connection (used as of DD v1.4.0) + - UCX_IB_SL=1 # Force IB SL1 with Adaptive Routing (AR) + - UCX_DC_MAX_NUM_EPS=512 # Allow 512 peers for DC transport + - UCX_RC_MAX_NUM_EPS=512 # Allow 512 peers for RC transport + - O2_PARTITION={{ environment_id }} + stdout: "{{ log_task_stdout }}" + stderr: "{{ log_task_stderr }}" + shell: true + user: "{{ user }}" + value: "{{ len(modulepath)>0 ? _module_cmdline : _plain_cmdline }}" + arguments: + - "--cpunodebind=0" + - "--preferred=0" + - "--" + - "{{ o2_install_path }}/bin/StfSender" + - "--session=default" + - "--shm-segment-id=2" + - "--shm-segment-size={{ stfs_shm_segment_size }}" + - "--dd-region-size={{ stfs_dd_region_size }}" + - "--dd-region-id=3536" + - "--transport=shmem" + - "--input-channel-name={{ stfs_input_channel_name }}" + - "--severity={{ fmq_severity }}" + - "--severity-infologger={{ infologger_severity }}" + - "--monitoring-backend={{ monitoring_dd_url }}" + - "--monitoring-process-interval={{ monitoring_dd_interval }}" + - "--discovery-partition={{ environment_id }}" + - "--discovery-id={{ dd_discovery_stfs_id }}" + - "--discovery-endpoint={{ dd_discovery_endpoint }}" + - "--discovery-net-if={{ dd_discovery_net_if }}" + - '{{ ddsched_enabled == "true" ? "" : "--stand-alone" }}' + - "--shm-monitor=false" + - "{{ stfs_enable_datasink == 'true' ? '--data-sink-enable' : ' ' }}" + - "{{ stfs_enable_datasink == 'true' ? '--data-sink-dir=' + stfs_datasink_dir : ' ' }}" + - "{{ stfs_enable_datasink == 'true' ? '--data-sink-max-stfs-per-file=0' : ' ' }}" + - "{{ stfs_enable_datasink == 'true' ? '--data-sink-max-file-size=' + stfs_datasink_filesize : ' ' }}" diff --git a/core/task/manager.go b/core/task/manager.go index 9c96b83d..ae220022 100644 --- a/core/task/manager.go +++ b/core/task/manager.go @@ -33,6 +33,7 @@ import ( "sync" "time" + "github.com/AliceO2Group/Control/common/controlmode" "github.com/AliceO2Group/Control/common/utils/safeacks" "github.com/AliceO2Group/Control/apricot" @@ -51,6 +52,7 @@ import ( "github.com/spf13/viper" "gopkg.in/yaml.v3" + k8sclient "github.com/AliceO2Group/Control/control-operator/pkg/client" "github.com/AliceO2Group/Control/core/controlcommands" "github.com/AliceO2Group/Control/core/task/channel" "github.com/k0kubun/pp" @@ -103,6 +105,9 @@ type Manager struct { internalEventCh chan<- event.Event ackKilledTasks *safeacks.SafeAcks killTasksMu sync.Mutex // to avoid races when attempting to kill the same tasks in different goroutines + + k8sClient *k8sclient.Client + k8sEnvs *k8sEnvRegistry } func NewManager(shutdown func(), internalEventCh chan<- event.Event) (taskman *Manager, err error) { @@ -144,6 +149,13 @@ func NewManager(shutdown func(), internalEventCh chan<- event.Event) (taskman *M taskman.tasksToDeploy = taskman.schedulerState.tasksToDeploy taskman.reviveOffersTrg = taskman.schedulerState.reviveOffersTrg taskman.ackKilledTasks = safeacks.NewAcks() + taskman.k8sEnvs = newK8sEnvRegistry() + if k8sClient, k8sErr := newK8sClientFromViper(); k8sErr != nil { + log.WithError(k8sErr).Warn("K8s client init failed, K8s tasks disabled") + } else { + log.Info("K8s client initiated") + taskman.k8sClient = k8sClient + } schedState.setupCli() @@ -476,6 +488,33 @@ func (m *Manager) acquireTasks(envId uid.ID, taskDescriptors Descriptors) (err e tasksToRun = append(tasksToRun, taskDescriptors...) } + // Split K8s descriptors out before the Mesos retry loop. + var k8sDescriptors Descriptors + { + mesos := make(Descriptors, 0, len(tasksToRun)) + for _, desc := range tasksToRun { + class, ok := m.classes.GetClass(desc.TaskClassName) + if ok && class != nil && (class.Control.Mode == controlmode.KUBERNETES_DIRECT || + class.Control.Mode == controlmode.KUBERNETES_FAIRMQ) { + k8sDescriptors = append(k8sDescriptors, desc) + } else { + mesos = append(mesos, desc) + } + } + tasksToRun = mesos + } + + var k8sDeployed DeploymentMap + var k8sDeployErr error + if len(k8sDescriptors) > 0 { + if m.k8sClient == nil { + k8sDeployErr = fmt.Errorf("K8s client not configured") + } else { + // TODO: this is synchronous call it would be worth it to make it async, so mesos loop doesn't have to wait for k8s + k8sDeployed, k8sDeployErr = m.deployKubernetesTasks(context.Background(), envId, k8sDescriptors) + } + } + // TODO: fill out tasksToTeardown in the previous loop //if len(tasksToTeardown) > 0 { // err = m.TeardownTasks(tasksToTeardown) @@ -617,6 +656,32 @@ func (m *Manager) acquireTasks(envId uid.ID, taskDescriptors Descriptors) (err e } } + // Merge K8s deployment results into unified tracking. + if k8sDeployErr != nil { + logWithId.WithError(k8sDeployErr).Error("K8s task deployment failed") + for _, desc := range k8sDescriptors { + if desc.TaskRole.GetTaskTraits().Critical { + deploymentSuccess = false + undeployableCriticalDescriptors = append(undeployableCriticalDescriptors, desc) + undeployableDescriptors = append(undeployableDescriptors, desc) + } else { + undeployableNonCriticalDescriptors = append(undeployableNonCriticalDescriptors, desc) + undeployableDescriptors = append(undeployableDescriptors, desc) + } + } + } else { + logWithId.Infof("succeeded to deploy %d kubernetes tasks", len(k8sDeployed)) + for taskPtr, desc := range k8sDeployed { + taskPtr.SetParent(desc.TaskRole) + if !taskPtr.IsLocked() { + log.WithField("task", taskPtr.taskId).Warning("K8s task not locked after deployment") + deploymentSuccess = false + } + allDeployedTasks[taskPtr] = desc + desc.TaskRole.UpdateStatus(ACTIVE) + } + } + log.Infof("Succeeded to deploy %d/%d tasks", len(allDeployedTasks), len(tasksToRun)) { @@ -667,6 +732,13 @@ func (m *Manager) acquireTasks(envId uid.ID, taskDescriptors Descriptors) (err e } func (m *Manager) releaseTasks(envId uid.ID, tasks Tasks) { + if m.k8sClient != nil { + if err := m.killK8sEnvironment(context.Background(), envId); err != nil { + log.WithError(err).WithField("partition", envId.String()). + Warn("failed to delete K8s Environment CRD during release") + } + } + taskReleaseErrors := make(map[string]error) taskIdsReleased := make([]string, 0) @@ -701,18 +773,21 @@ func (m *Manager) releaseTask(envId uid.ID, task *Task) error { } func (m *Manager) configureTasks(envId uid.ID, tasks Tasks) error { - notify := make(chan controlcommands.MesosCommandResponse) - receivers, err := tasks.GetMesosCommandTargets() - if err != nil { - return err - } - - if tasks == nil || len(tasks) == 0 { - return fmt.Errorf("empty task list to configure for environment %s", envId.String()) + var k8sTasks Tasks + var mesosTasks Tasks + for _, t := range tasks { + if t.GetControlMode() == controlmode.KUBERNETES_DIRECT || + t.GetControlMode() == controlmode.KUBERNETES_FAIRMQ { + k8sTasks = append(k8sTasks, t) + } else { + mesosTasks = append(mesosTasks, t) + } } // We fetch each task's local bindMap to generate a global bindMap for the whole Tasks slice, // i.e. a map of the paths of registered inbound channels and their ports. + // We use the full task list (including K8s tasks) so that Mesos tasks can resolve + // connect targets that point at K8s task channels. bindMap := make(channel.BindMap) for _, task := range tasks { if task.GetParent() == nil { // Crash reported here by Roberto 6/2022 @@ -743,11 +818,27 @@ func (m *Manager) configureTasks(envId uid.ID, tasks Tasks) error { log.WithFields(logrus.Fields{"bindMap": pp.Sprint(bindMap), "envId": envId.String()}). Debug("generated inbound bindMap for environment configuration") + if len(k8sTasks) > 0 && m.k8sClient != nil { + if err := m.configureK8sTasks(context.Background(), envId, k8sTasks, bindMap); err != nil { + return err + } + } + + if len(mesosTasks) == 0 { + return nil + } + + notify := make(chan controlcommands.MesosCommandResponse) + receivers, err := mesosTasks.GetMesosCommandTargets() + if err != nil { + return err + } + src := sm.STANDBY.String() evt := "CONFIGURE" dest := sm.CONFIGURED.String() args := make(controlcommands.PropertyMapsMap) - args, err = tasks.BuildPropertyMaps(bindMap) + args, err = mesosTasks.BuildPropertyMaps(bindMap) if err != nil { return err } @@ -811,6 +902,28 @@ func (m *Manager) configureTasks(envId uid.ID, tasks Tasks) error { } func (m *Manager) transitionTasks(envId uid.ID, tasks Tasks, src string, event string, dest string, commonArgs controlcommands.PropertyMap) error { + var mesosTasks Tasks + + for _, t := range tasks { + if t.GetControlMode() != controlmode.KUBERNETES_DIRECT && + t.GetControlMode() != controlmode.KUBERNETES_FAIRMQ { + mesosTasks = append(mesosTasks, t) + } + } + + if len(mesosTasks) == 0 { + return nil + } + + if len(tasks) != len(mesosTasks) { + log.WithField("partition", envId).Infof("Transitioning k8s environment from %s, to %s, event: %s", src, dest, event) + if err := m.transitionAndWaitK8sEnvState(context.Background(), envId, strings.ToLower(dest)); err != nil { + return err + } + } + + tasks = mesosTasks + notify := make(chan controlcommands.MesosCommandResponse) receivers, err := tasks.GetMesosCommandTargets() if err != nil { @@ -1128,6 +1241,17 @@ func (m *Manager) KillTasks(taskIds []string) (killed Tasks, running Tasks, err } func (m *Manager) doKillTask(task *Task) error { + if task.GetControlMode() == controlmode.KUBERNETES_DIRECT || + task.GetControlMode() == controlmode.KUBERNETES_FAIRMQ { + if m.k8sClient != nil { + if err := m.killK8sTask(context.Background(), task); err != nil { + return err + } + } + // K8s delete is synchronous — send the ack immediately so KillTasks doesn't block. + _ = m.ackKilledTasks.TrySendAck(task.taskId) + return nil + } return m.schedulerState.killTask(context.TODO(), task.GetMesosCommandTarget()) } @@ -1178,6 +1302,10 @@ func (m *Manager) Start(ctx context.Context) { m.schedulerState.Start(ctx) + if m.k8sClient != nil { + go m.watchK8sTasks(ctx) + } + go func() { for { select { diff --git a/core/task/managerk8s.go b/core/task/managerk8s.go new file mode 100644 index 00000000..6367afa1 --- /dev/null +++ b/core/task/managerk8s.go @@ -0,0 +1,452 @@ +/* + * === This file is part of ALICE O² === + * + * Copyright 2026 CERN and copyright holders of ALICE O². + * Author: Michal Tichak + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In applying this license CERN does not waive the privileges and + * immunities granted to it by virtue of its status as an + * Intergovernmental Organization or submit itself to any jurisdiction. + */ + +package task + +import ( + "context" + "fmt" + "maps" + "strings" + "sync" + "time" + + corev1 "k8s.io/api/core/v1" + k8sapierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + + "github.com/AliceO2Group/Control/common/gera" + "github.com/AliceO2Group/Control/common/utils/uid" + "github.com/AliceO2Group/Control/control-operator/api/v1alpha1" + k8sclient "github.com/AliceO2Group/Control/control-operator/pkg/client" + "github.com/AliceO2Group/Control/core/task/channel" + "github.com/AliceO2Group/Control/core/task/sm" + "github.com/AliceO2Group/Control/core/task/taskclass" + "github.com/spf13/viper" +) + +// TODO: revisit all the timeouts in ECS. they shouldn't be hardcoded. +const ( + k8sDeployTimeout = 80 * time.Second + k8sTransitionTimeout = 80 * time.Second + k8sWatchRetryDelay = 5 * time.Second +) + +// k8sEnvRegistry maps ECS environment IDs to K8s Environment CRD names. +type k8sEnvRegistry struct { + mu sync.RWMutex + envs map[uid.ID]string +} + +func newK8sEnvRegistry() *k8sEnvRegistry { + return &k8sEnvRegistry{envs: make(map[uid.ID]string)} +} + +func (r *k8sEnvRegistry) set(envId uid.ID, crdName string) { + r.mu.Lock() + r.envs[envId] = crdName + r.mu.Unlock() +} + +func (r *k8sEnvRegistry) get(envId uid.ID) (string, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + crdName, ok := r.envs[envId] + return crdName, ok +} + +func (r *k8sEnvRegistry) delete(envId uid.ID) { + r.mu.Lock() + delete(r.envs, envId) + r.mu.Unlock() +} + +// newK8sClientFromViper creates a K8s client from viper config. +// Returns nil, nil if kubeNamespace is not configured (K8s disabled). +func newK8sClientFromViper() (*k8sclient.Client, error) { + namespace := viper.GetString("kubeNamespace") + if namespace == "" { + return nil, nil + } + kubeconfig := viper.GetString("kubeconfig") + return k8sclient.New(kubeconfig, namespace) +} + +type k8sTaskEntry struct { + task *Task + desc *Descriptor +} + +// deployKubernetesTasks deploys all KUBERNETES-mode descriptors by creating one Environment CRD that +// references the pre-deployed TaskTemplate CRDs. It blocks until the operator reports status.state == "standby". +func (m *Manager) deployKubernetesTasks(ctx context.Context, envId uid.ID, descriptors Descriptors) (DeploymentMap, error) { + log.WithField("partition", envId). + WithField("count", len(descriptors)). + Info("deploying K8s tasks") + + entries, err := m.createK8sTaskEntries(envId, descriptors) + if err != nil { + log.WithField("partition", envId).WithError(err).Error("failed to create K8s task entries") + return nil, err + } + + nodeToRefs, err := m.buildK8sNodeTaskRefs(entries) + if err != nil { + log.WithField("partition", envId).WithError(err).Error("failed to build K8s node task refs") + return nil, err + } + + for _, e := range entries { + m.roster.append(e.task) + } + + envCRDName, err := m.createK8sEnvironmentCRD(ctx, envId, nodeToRefs) + if err != nil { + log.WithField("partition", envId).WithError(err).Error("failed to create K8s Environment CRD") + return nil, err + } + + log.WithField("partition", envId). + WithField("crd", envCRDName). + Infof("K8s Environment CRD created, waiting up to %s for standby", k8sDeployTimeout) + + if err := m.waitForK8sEnvState(ctx, envCRDName, "standby", k8sDeployTimeout); err != nil { + log.WithField("partition", envId).WithField("crd", envCRDName).WithError(err).Error("K8s Environment did not reach standby") + return nil, fmt.Errorf("waiting for Environment %s standby: %w", envCRDName, err) + } + + log.WithField("partition", envId). + WithField("crd", envCRDName). + Infof("K8s Environment reached standby, %d tasks deployed", len(entries)) + + deployed := make(DeploymentMap, len(entries)) + for _, e := range entries { + deployed[e.task] = e.desc + } + return deployed, nil +} + +func (m *Manager) createK8sTaskEntries(envId uid.ID, descriptors Descriptors) ([]k8sTaskEntry, error) { + entries := make([]k8sTaskEntry, 0, len(descriptors)) + for _, desc := range descriptors { + taskClass, ok := m.classes.GetClass(desc.TaskClassName) + if !ok || taskClass == nil { + return nil, fmt.Errorf("task class not found: %s", desc.TaskClassName) + } + + nodeName, err := nodeNameFromDescriptor(desc, taskClass) + if err != nil { + return nil, err + } + t := m.newTaskForKubernetes(desc, nodeName) + + wants, err := m.GetWantsForDescriptor(desc, envId) + if err != nil { + return nil, fmt.Errorf("getting wants for %s: %w", desc.TaskClassName, err) + } + + for _, ch := range wants.InboundChannels { + if ch.Addressing == channel.IPC { + t.localBindMap[ch.Name] = channel.NewBoundIpcEndpoint(ch.Transport) + } else { + log.WithField("task", desc.TaskClassName). + WithField("channel", ch.Name). + Warn("TCP inbound channel in K8s task — skipping port allocation") + } + if len(ch.Global) != 0 { + t.localBindMap["::"+ch.Global] = t.localBindMap[ch.Name] + } + } + + entries = append(entries, k8sTaskEntry{task: t, desc: desc}) + } + return entries, nil +} + +func (m *Manager) buildK8sNodeTaskRefs(entries []k8sTaskEntry) (map[string][]v1alpha1.TaskReference, error) { + nodeToRefs := make(map[string][]v1alpha1.TaskReference) + for _, e := range entries { + t := e.task + desc := e.desc + + taskClass, _ := m.classes.GetClass(desc.TaskClassName) + + if err := t.BuildTaskCommand(desc.TaskRole); err != nil { + return nil, fmt.Errorf("building task command for %s: %w", desc.TaskClassName, err) + } + cmd := t.GetTaskCommandInfo() + + for varName, defaultValue := range map[string]string{ + "O2_ROLE": t.hostname, + "O2_SYSTEM": "FLP", + } { + varIsSet := false + for _, e := range cmd.Env { + key, _, _ := strings.Cut(e, "=") + if key == varName { + varIsSet = true + break + } + } + if !varIsSet { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", varName, defaultValue)) + } + } + + argsCLI := make([]string, 0, len(cmd.Arguments)) + for _, arg := range cmd.Arguments { + if strings.TrimSpace(arg) != "" { + argsCLI = append(argsCLI, arg) + } + } + + ref := v1alpha1.TaskReference{ + Name: taskClass.Identifier.Name, + TaskID: t.taskId, + ArgsCLI: argsCLI, + Env: cmdEnvToK8sEnvVars(cmd.Env), + } + nodeToRefs[t.hostname] = append(nodeToRefs[t.hostname], ref) + } + return nodeToRefs, nil +} + +func (m *Manager) createK8sEnvironmentCRD(ctx context.Context, envId uid.ID, nodeToRefs map[string][]v1alpha1.TaskReference) (string, error) { + envCRDName := strings.ToLower(envId.String()) + + env := &v1alpha1.Environment{ + ObjectMeta: metav1.ObjectMeta{Name: envCRDName}, + TaskTemplates: v1alpha1.TemplateSpecification{ + Tasks: nodeToRefs, + }, + Spec: v1alpha1.EnvironmentSpec{ + Tasks: make(map[string][]v1alpha1.TaskDefinition), + State: "standby", + }, + } + if err := m.k8sClient.CreateEnvironment(ctx, env); err != nil { + return "", fmt.Errorf("creating Environment CRD %s: %w", envCRDName, err) + } + m.k8sEnvs.set(envId, envCRDName) + return envCRDName, nil +} + +// equivalent of newTaskForMesosOffer in manager.go +func (m *Manager) newTaskForKubernetes(desc *Descriptor, nodeName string) *Task { + newId := uid.New().String() + t := &Task{ + name: fmt.Sprintf("%s#%s", desc.TaskClassName, newId), + parent: desc.TaskRole, + className: desc.TaskClassName, + hostname: nodeName, + agentId: "kubernetes", + offerId: "kubernetes", + taskId: newId, + executorId: "kubernetes", + properties: gera.MakeMap[string, string]().Wrap(m.GetTaskClass(desc.TaskClassName).Properties), + localBindMap: make(channel.BindMap), + state: sm.STANDBY, + status: ACTIVE, + } + t.GetTaskClass = func() *taskclass.Class { + return m.GetTaskClass(t.className) + } + return t +} + +func (m *Manager) waitForK8sEnvState(ctx context.Context, envCRDName, expected string, timeout time.Duration) error { + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + // Check current state before watching in case it's already reached. + env, err := m.k8sClient.GetEnvironment(ctx, envCRDName) + if err != nil { + return fmt.Errorf("getting Environment %s: %w", envCRDName, err) + } + if env.Status.State == expected { + return nil + } + + watcher, err := m.k8sClient.WatchEnvironmentsFromVersion(ctx, env.ResourceVersion) + if err != nil { + return fmt.Errorf("watching Environments: %w", err) + } + defer watcher.Stop() + + for { + select { + case <-ctx.Done(): + return fmt.Errorf("timeout waiting for Environment %s to reach state %q: %w", envCRDName, expected, ctx.Err()) + case ev, ok := <-watcher.ResultChan(): + if !ok { + return fmt.Errorf("watch channel closed waiting for Environment %s", envCRDName) + } + env, ok := ev.Object.(*v1alpha1.Environment) + if !ok { + continue + } + log.WithField("partition", envCRDName). + WithField("crd", envCRDName).Debug("received some environment update") + if env.Name == envCRDName { + log.WithField("crd", envCRDName). + WithField("state", env.Status.State). + WithField("expected", expected). + Debug("K8s Environment state update received") + if env.Status.State == expected { + return nil + } + } + } + } +} + +// configureK8sTasks is necessary addition to transitionAndWaitK8sEnvState because we need to pass generated +// channels to individual tasks. These are generated during Configure transition +func (m *Manager) configureK8sTasks(ctx context.Context, envId uid.ID, tasks Tasks, bindMap channel.BindMap) error { + for _, t := range tasks { + propMap, err := t.BuildPropertyMap(bindMap) + if err != nil { + return fmt.Errorf("building property map for K8s task %s: %w", t.GetClassName(), err) + } + + k8sTaskList, err := m.k8sClient.ListTasksByLabel(ctx, map[string]string{"taskID": t.taskId}) + if err != nil { + return fmt.Errorf("error while listing K8s Task CRD for task %s: %w", t.taskId, err) + } + if len(k8sTaskList) == 0 { + return fmt.Errorf("there were not tasks for taskId %s", t.taskId) + } else if len(k8sTaskList) > 1 { + return fmt.Errorf("there was more than one task for taskId %s", t.taskId) + } + + k8sTask := k8sTaskList[0] + if k8sTask.Spec.Arguments == nil { + k8sTask.Spec.Arguments = make(map[string]string) + } + maps.Copy(k8sTask.Spec.Arguments, propMap) + if err := m.k8sClient.UpdateTask(ctx, &k8sTask); err != nil { + return fmt.Errorf("updating arguments for K8s Task CRD %s: %w", k8sTask.Name, err) + } + } + return m.transitionAndWaitK8sEnvState(ctx, envId, "configured") +} + +// transitionAndWaitK8sEnvState is the easy way to transition tasks. Posibility for future: make this async, +// so we don't have to wait during deployment +func (m *Manager) transitionAndWaitK8sEnvState(ctx context.Context, envId uid.ID, targetState string) error { + crdName, ok := m.k8sEnvs.get(envId) + if !ok { + return fmt.Errorf("no K8s Environment CRD registered for env %s", envId) + } + env, err := m.k8sClient.GetEnvironment(ctx, crdName) + if err != nil { + return fmt.Errorf("error getting Environment CRD %s: %w", crdName, err) + } + env.Spec.State = targetState + if err := m.k8sClient.UpdateEnvironment(ctx, env); err != nil { + return fmt.Errorf("updating Environment CRD %s: %w", crdName, err) + } + return m.waitForK8sEnvState(ctx, crdName, targetState, k8sTransitionTimeout) +} + +func (m *Manager) killK8sEnvironment(ctx context.Context, envId uid.ID) error { + crdName, ok := m.k8sEnvs.get(envId) + if !ok { + return nil + } + if err := m.k8sClient.DeleteEnvironment(ctx, crdName); err != nil { + return fmt.Errorf("deleting Environment CRD %s: %w", crdName, err) + } + m.k8sEnvs.delete(envId) + return nil +} + +func (m *Manager) killK8sTask(ctx context.Context, task *Task) error { + err := m.k8sClient.DeleteTask(ctx, task.taskId) + if k8sapierrors.IsNotFound(err) { + return nil + } + return err +} + +func (m *Manager) watchK8sTasks(ctx context.Context) { + for ctx.Err() == nil { + watcher, err := m.k8sClient.WatchTasks(ctx) + if err != nil { + log.WithError(err).Warnf("failed to start K8s task watcher, retrying after %v", k8sWatchRetryDelay) + time.Sleep(k8sWatchRetryDelay) + continue + } + messages: + for { + select { + case <-ctx.Done(): + watcher.Stop() + return + case ev, ok := <-watcher.ResultChan(): + if !ok { + break messages + } + m.process(ev) + } + } + } +} + +func (m *Manager) process(ev watch.Event) { + k8sTask, ok := ev.Object.(*v1alpha1.Task) + if !ok || k8sTask.Status.State == "" { + return + } + if taskId, ok := k8sTask.Labels["taskID"]; ok && taskId != "" { + m.updateTaskState(taskId, strings.ToUpper(k8sTask.Status.State)) + } +} + +// nodeNameFromDescriptor extracts the target K8s node name from the merged constraints. +// Workflows pin tasks to a host via a machine_id constraint (set by the per-host for loop +// in workflow templates). Returns an error if no machine_id constraint is found, since K8s +// tasks require an explicit node target (there is no offer mechanism to derive it from). +func nodeNameFromDescriptor(desc *Descriptor, taskClass *taskclass.Class) (string, error) { + merged := desc.RoleConstraints.MergeParent(taskClass.Constraints) + for _, c := range merged { + if c.Attribute == "machine_id" { + return c.Value, nil + } + } + return "", fmt.Errorf("task class %q has no machine_id constraint: K8s tasks require a machine_id constraint to select the target node", desc.TaskClassName) +} + +// cmdEnvToK8sEnvVars converts a slice of "KEY=VALUE" strings to Kubernetes EnvVar objects. +func cmdEnvToK8sEnvVars(env []string) []corev1.EnvVar { + vars := make([]corev1.EnvVar, 0, len(env)) + for _, e := range env { + parts := strings.SplitN(e, "=", 2) + if len(parts) == 2 { + vars = append(vars, corev1.EnvVar{Name: parts[0], Value: parts[1]}) + } + } + return vars +} diff --git a/core/task/task.go b/core/task/task.go index bee19a1b..2bea663b 100644 --- a/core/task/task.go +++ b/core/task/task.go @@ -288,7 +288,9 @@ func (t *Task) BuildTaskCommand(role parentRole) (err error) { class.Control.Mode == controlmode.DIRECT || class.Control.Mode == controlmode.FAIRMQ || class.Control.Mode == controlmode.KUBECTL_DIRECT || - class.Control.Mode == controlmode.KUBECTL_FAIRMQ { + class.Control.Mode == controlmode.KUBECTL_FAIRMQ || + class.Control.Mode == controlmode.KUBERNETES_DIRECT || + class.Control.Mode == controlmode.KUBERNETES_FAIRMQ { var varStack map[string]string // First we get the full varStack from the parent role, and @@ -396,7 +398,8 @@ func (t *Task) BuildTaskCommand(role parentRole) (err error) { } if class.Control.Mode == controlmode.FAIRMQ || - class.Control.Mode == controlmode.KUBECTL_FAIRMQ { + class.Control.Mode == controlmode.KUBECTL_FAIRMQ || + class.Control.Mode == controlmode.KUBERNETES_FAIRMQ { // FIXME read this from configuration // if the task class doesn't provide an id, we generate one ourselves if !utils.StringSliceContains(cmd.Arguments, "--id") { @@ -640,7 +643,9 @@ func (t *Task) BuildPropertyMap(bindMap channel.BindMap) (propMap controlcommand if class.Control.Mode == controlmode.FAIRMQ || class.Control.Mode == controlmode.DIRECT || class.Control.Mode == controlmode.KUBECTL_DIRECT || - class.Control.Mode == controlmode.KUBECTL_FAIRMQ { + class.Control.Mode == controlmode.KUBECTL_FAIRMQ || + class.Control.Mode == controlmode.KUBERNETES_DIRECT || + class.Control.Mode == controlmode.KUBERNETES_FAIRMQ { for _, inbCh := range channel.MergeInbound(parent.CollectInboundChannels(), class.Bind) { // We get the FairMQ-formatted propertyMap from the inbound channel spec var chanProps controlcommands.PropertyMap diff --git a/docs/kubernetes_ecs.md b/docs/kubernetes_ecs.md index dfe89e03..8dc17cb0 100644 --- a/docs/kubernetes_ecs.md +++ b/docs/kubernetes_ecs.md @@ -8,12 +8,13 @@ While prototyping we used many Kubernetes clusters, namely [`kind`](https://kind.sigs.k8s.io/), [`minikube`](https://minikube.sigs.k8s.io/docs/) and [`k3s`](https://k3s.io/) in both local and remote cluster deployment. We used Openstack for remote deployment. Follow the guides at the individual distributions in order to create the desired cluster setup. -k3s is recommended to run this prototype, as it is lightweight -and easily installed distribution which is also [`CNCF`](https://www.cncf.io/training/certification/) certified. +k3s is recommended to run this prototype, as it is lightweight and easily installed distribution +which is also [`CNCF`](https://www.cncf.io/training/certification/) certified. However kubernetes +operator patterns used in this repo should be k8s distribution agnostic. All settings of `k3s` were used as default except one: locked-in-memory size. Use `ulimit -l` to learn what is the limit for the current user and `LimitMEMLOCK` inside the k3s systemd service config -to set it for correct value. Right now the `flp` user has unlimited size (`LimitMEMLOCK=infinity`). +to set it for correct value. Right now the `flp` user should have unlimited size (`LimitMEMLOCK=infinity`). This config is necessary because even if you are running Pods with the privileged security context under user flp, Kubernetes still sets limits according to its internal settings and doesn't respect linux settings. @@ -23,14 +24,41 @@ is ability to run Pods with privileged permissions and also under user `flp`. This means that the machine has to have `flp` user setup the same way as if you would do the installation with [`o2-flp-setup`](https://alice-flp.docs.cern.ch/Operations/Experts/system-configuration/utils/o2-flp-setup/). -## Task Controller +## Operator pattern -Following text assumes that there is a Task Controller from `control-operator` running -at your K8s cluster and Task CRD installed at your cluster. -You can find the details about the usage in the [documentation](/control-operator/README.md). +Any communication between kubernetes and OCC tasks and ECS and kubernetes is based on [operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/). +All operator pattern code implemented and expected to be used and deployed by ECS is located in the folder `control-operator` +with [README.md](/control-operator/README.md). + +## Direct ECS <-> Kubernetes bridge + +Apart from the old way of deploying tasks via Apache Mesos ECS now supports deployment of tasks +directly to the Kubernetes as well and it is up to Admin/User to decide where the task should run. +In order for Task to be deployed in Kubernetes cluster we need to have environment and task managers +running inside the cluster as these are responsible for managing Custom Resource Definitions of Task and Environment. + +The bridge works as follows: + +1. **ECS core** (running outside the cluster) uses a typed Kubernetes client (`control-operator/pkg/client`) backed by `controller-runtime` to interact with the cluster. +2. When ECS deploys a task whose control mode is `kubernetes_direct` or `kubernetes_fairmq`, it creates a **Task CRD** and, if needed, an **Environment CRD** in the cluster instead of submitting a Mesos offer. +3. Inside the cluster, the **task-manager** and **environment-manager** operators (see `control-operator/cmd/`) watch these CRDs and reconcile the desired state — scheduling Pods, driving OCC gRPC state transitions, and writing status back into the CRD. +4. ECS watches the CRDs via the Kubernetes Watch API and reacts to status changes exactly as it would to Mesos task updates, keeping the rest of the ECS state machine intact. + +This design lets ECS reuse its existing environment lifecycle, configuration generation, and monitoring logic while outsourcing Pod scheduling and OCC communication to the in-cluster operators. The relevant code can be found in manager.go and managerk8s.go. +The manager.go implements the split between Mesos and K8s tasks while managerk8s.go implements actual creation, deployment, transitioning and updating ECS structure. + +To deploy a Kubernetes task you can in principle reuse existing control-workflow task YAML manifests by changing the control mode to `kubernetes_direct` or `kubernetes_fairmq`. But in practice there can be issues +with reusing existing manifests, for example bad quotation of arguments: Mesos runs tasks via shell, which interpreted and stripped quotation from commands. For this reason you can find ready-to-use manifests with all necessary changes +inside `control-operator/ecs-manifests/control-workflows/*kube-direct*`. ## Running tasks (`KubectlTask`) +This method is obsoleted by direct ECS <-> Kubernetes bridge. However it should still work +for debugging purposes. It is maintained on a best-effort basis only. + +To use KubectlTasks you need to have Task controller running in k8s cluster. +You can find the details about the usage in the [documentation](/control-operator/README.md). + ECS is setup to run tasks through Mesos on all required hosts baremetal with active task management (see [`ControllableTask`](/executor/executable/controllabletask.go)) and OCC gRPC communication. When running docker task through ECS we could easily diff --git a/go.mod b/go.mod index 9800a957..5ae1a461 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,10 @@ replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16 replace github.com/armon/go-metrics => github.com/hashicorp/go-metrics v0.5.3 +replace github.com/AliceO2Group/Control/control-operator => ./control-operator + require ( + github.com/AliceO2Group/Control/control-operator v0.0.0 github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect @@ -45,15 +48,15 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/osamingo/indigo v1.1.1 github.com/pborman/uuid v1.2.1 - github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_golang v1.23.2 github.com/pseudomuto/protoc-gen-doc v1.5.1 github.com/rivo/tview v0.0.0-20240307173318-e804876934a1 github.com/rs/xid v1.5.0 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/kafka-go v0.4.47 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.8.0 - github.com/spf13/pflag v1.0.5 + github.com/spf13/cobra v1.10.0 + github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.18.2 github.com/teo/logrus-prefixed-formatter v0.5.3-0.20230717095749-669d57324f0a github.com/valyala/fasttemplate v1.2.2 @@ -63,7 +66,7 @@ require ( golang.org/x/sys v0.43.0 google.golang.org/grpc v1.79.3 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.36.10 + google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) @@ -75,37 +78,56 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/iancoleman/strcase v0.3.0 github.com/influxdata/line-protocol/v2 v2.2.1 - github.com/onsi/ginkgo/v2 v2.19.0 - github.com/onsi/gomega v1.34.1 + github.com/onsi/ginkgo/v2 v2.27.2 + github.com/onsi/gomega v1.38.2 github.com/swaggo/http-swagger/v2 v2.0.2 github.com/swaggo/swag v1.16.3 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f + k8s.io/api v0.35.0 + k8s.io/apimachinery v0.35.0 ) require ( github.com/KyleBanks/depth v1.2.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/armon/go-metrics v0.5.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.6.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/cyphar/filepath-securejoin v0.6.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/gdamore/encoding v1.0.1 // 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-logr/logr v1.4.3 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/jsonpointer v0.22.4 // indirect + github.com/go-openapi/jsonreference v0.21.4 // indirect github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/swag v0.25.4 // 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-task/slim-sprig/v3 v3.0.0 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/google/gnostic-models v0.7.1 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // 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.2 // indirect @@ -118,15 +140,13 @@ require ( github.com/imdario/mergo v0.3.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect @@ -134,6 +154,9 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-proto-validators v0.3.2 // indirect github.com/naoina/go-stringutil v0.1.0 // indirect github.com/osamingo/base58 v1.0.0 // indirect @@ -142,9 +165,9 @@ require ( github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pjbgf/sha1cd v0.6.0 // indirect github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.50.0 // indirect - github.com/prometheus/procfs v0.13.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.19.2 // indirect github.com/pseudomuto/protokit v0.2.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -159,19 +182,32 @@ require ( github.com/swaggo/files/v2 v2.0.0 // indirect github.com/urfave/cli/v2 v2.3.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.35.0 // indirect + golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/term v0.42.0 // indirect golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.44.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + k8s.io/client-go v0.35.0 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e // indirect + k8s.io/utils v0.0.0-20260108192941-914a6e750570 // indirect + sigs.k8s.io/controller-runtime v0.23.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) replace github.com/codahale/hdrhistogram => github.com/HdrHistogram/hdrhistogram-go v1.0.1 diff --git a/go.sum b/go.sum index da0b3cb4..534b7427 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +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 v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= @@ -41,9 +43,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp 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/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.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= @@ -57,10 +58,14 @@ github.com/dmarkham/enumer v1.5.11 h1:quorLCaEfzjJ23Pf7PB9lyyaHseh91YfTM/sAD/4Mb github.com/dmarkham/enumer v1.5.11/go.mod h1:yixql+kDDQRYqcuBM2n9Vlt7NoT9ixgXhaXry8vmRg8= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= +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/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/expr-lang/expr v1.17.7 h1:Q0xY/e/2aCIp8g9s/LGvMDCC5PxYlvHgDZRQ4y16JX8= github.com/expr-lang/expr v1.17.7/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -75,13 +80,21 @@ github.com/frankban/quicktest v1.11.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +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/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= +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-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -100,19 +113,55 @@ 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.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +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.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +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/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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/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/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -125,8 +174,10 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +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/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= +github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= 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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -134,8 +185,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +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/uuid v1.0.0/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= @@ -208,10 +259,12 @@ 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/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -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/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= +github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= @@ -223,8 +276,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +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/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -245,8 +298,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -268,6 +321,8 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mesos/mesos-go v0.0.11 h1:jMp9+W3zLu46g8EuP2su2Sjj7ipBh4N/g65c0kzGl/8= github.com/mesos/mesos-go v0.0.11/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= +github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= +github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= 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/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= @@ -284,9 +339,15 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 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/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/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/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos= github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w= @@ -297,10 +358,10 @@ github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 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/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +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/osamingo/base58 v1.0.0 h1:NhsHxeyMRaD5Li67LgdZG+4/rlyaNr9rVqYQxNGLOYg= github.com/osamingo/base58 v1.0.0/go.mod h1:nADsGCd4fm122SrLUaut+PhzCVwyvchAgxxBVDS5Wf8= github.com/osamingo/indigo v1.1.1 h1:tjPwqwZIq6pqUzfMxCKQeSaFRW0MzLrdT3lszGqYSpg= @@ -333,22 +394,22 @@ github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BU 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.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +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-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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +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.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.50.0 h1:YSZE6aa9+luNa2da6/Tik0q0A5AbR+U003TItK57CPQ= -github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ= +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.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= -github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= +github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= +github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/pseudomuto/protoc-gen-doc v1.5.1 h1:Ah259kcrio7Ix1Rhb6u8FCaOkzf9qRBqXnvAufg061w= github.com/pseudomuto/protoc-gen-doc v1.5.1/go.mod h1:XpMKYg6zkcpgfpCfQ8GcWBDRtRxOmMR5w7pz4Xo+dYM= github.com/pseudomuto/protokit v0.2.1 h1:kCYpE3thoR6Esm0CUvd5xbrDTOZPvQPTDeyXpZfrJdk= @@ -393,17 +454,19 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.10.0 h1:a5/WeUlSDCvV5a45ljW2ZFtV0bTDpkfSAj3uqB6Sc+0= +github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE= +github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +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.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= 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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -424,6 +487,14 @@ github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= github.com/teo/logrus-prefixed-formatter v0.5.3-0.20230717095749-669d57324f0a h1:iFCCEcdQHtGCeBv3zQOq67yIoVSubAMoPKnDUSfEw9M= github.com/teo/logrus-prefixed-formatter v0.5.3-0.20230717095749-669d57324f0a/go.mod h1:76q+dZ4qOCuYrqwoUUjVCuAXF1TXB4jc98eaZFo6Yh0= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +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/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -431,6 +502,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +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/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/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -456,8 +529,16 @@ go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2W 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.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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/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= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= @@ -492,6 +573,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.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.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= 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= @@ -557,6 +640,8 @@ 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/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -575,20 +660,26 @@ 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/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= 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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= @@ -598,11 +689,32 @@ 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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY= +k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA= +k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4= +k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU= +k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8= +k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE= +k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e h1:iW9ChlU0cU16w8MpVYjXk12dqQ4BPFBEgif+ap7/hqQ= +k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY= +k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +sigs.k8s.io/controller-runtime v0.23.0 h1:Ubi7klJWiwEWqDY+odSVZiFA0aDSevOCXpa38yCSYu8= +sigs.k8s.io/controller-runtime v0.23.0/go.mod h1:DBOIr9NsprUqCZ1ZhsuJ0wAnQSIxY/C6VjZbmLgw0j0= +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/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/v6 v6.3.1 h1:JrhdFMqOd/+3ByqlP2I45kTOZmTRLBUm5pvRjeheg7E= +sigs.k8s.io/structured-merge-diff/v6 v6.3.1/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=