diff --git a/.gitignore b/.gitignore index 4071b56..747a3cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin/ .vscode cover.out +.codegraph \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100755 index 63418fe..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributing - -Please check out the [contributing section](https://docs.metal-stack.io/stable/development/contributing/) in our [docs](https://docs.metal-stack.io/). \ No newline at end of file diff --git a/Makefile b/Makefile index ff083ea..ac0b7a1 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ GITVERSION := $(shell git describe --long --all) BUILDDATE := $(shell date -Iseconds) VERSION := $(or ${VERSION},$(shell git describe --tags --exact-match 2> /dev/null || git symbolic-ref -q --short HEAD || git rev-parse --short HEAD)) -CONTROLLER_TOOLS_VERSION ?= v0.20.0 +CONTROLLER_TOOLS_VERSION ?= v0.21.0 LOCALBIN ?= $(shell pwd)/bin CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen ENVTEST ?= $(LOCALBIN)/setup-envtest diff --git a/api/v2/config/controller.go b/api/v2/config/controller.go index 8a607e3..f3d654c 100644 --- a/api/v2/config/controller.go +++ b/api/v2/config/controller.go @@ -4,9 +4,10 @@ import ( "fmt" "time" + apiv2client "github.com/metal-stack/api/go/client" + v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/api/v2/helper" - metalgo "github.com/metal-stack/metal-go" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -47,9 +48,11 @@ type NewControllerConfig struct { SSHKeySecretName string // Metal is the metal client for accessing the metal-api. - Metal metalgo.Client + Metal apiv2client.Client // ClusterTag is the tag used in the metal-api for new firewalls to associate them with the cluster. ClusterTag string + // Project of this cluster + Project string // SafetyBackoff is used for guarding the metal-api when it comes to creating new firewalls. SafetyBackoff time.Duration @@ -83,8 +86,9 @@ type ControllerConfig struct { sshKeySecretNamespace string sshKeySecretName string - metal metalgo.Client + metal apiv2client.Client clusterTag string + project string safetyBackoff time.Duration progressDeadline time.Duration @@ -117,6 +121,7 @@ func New(c *NewControllerConfig) (*ControllerConfig, error) { shootAccessHelper: helper, metal: c.Metal, clusterTag: c.ClusterTag, + project: c.Project, safetyBackoff: c.SafetyBackoff, progressDeadline: c.ProgressDeadline, firewallHealthTimeout: c.FirewallHealthTimeout, @@ -248,14 +253,16 @@ func (c *ControllerConfig) GetSSHKeySecretNamespace() string { return c.sshKeySecretNamespace } -func (c *ControllerConfig) GetMetal() metalgo.Client { +func (c *ControllerConfig) GetMetal() apiv2client.Client { return c.metal } func (c *ControllerConfig) GetClusterTag() string { return c.clusterTag } - +func (c *ControllerConfig) GetProject() string { + return c.project +} func (c *ControllerConfig) GetSafetyBackoff() time.Duration { return c.safetyBackoff } diff --git a/api/v2/types_firewall.go b/api/v2/types_firewall.go index c8cf401..bc0d905 100644 --- a/api/v2/types_firewall.go +++ b/api/v2/types_firewall.go @@ -263,6 +263,8 @@ type FirewallNetwork struct { Prefixes []string `json:"prefixes,omitempty"` // Vrf is vrf id of this network. Vrf *int64 `json:"vrf"` + // Project of this network + Project *string `json:"project,omitempty"` } // FirewallList contains a list of firewalls diff --git a/api/v2/types_firewall_test.go b/api/v2/types_firewall_test.go index 142a912..97d64f2 100644 --- a/api/v2/types_firewall_test.go +++ b/api/v2/types_firewall_test.go @@ -6,7 +6,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/metal-stack/metal-lib/pkg/pointer" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "testing/synctest" @@ -190,7 +189,7 @@ func Test_EvaluateFirewallStatus(t *testing.T) { want: &FirewallStatusEvalResult{ Result: FirewallStatusUnhealthy, Reason: "not all health conditions are true: [SeedConnected]", - TimeoutIn: pointer.Pointer(5 * time.Minute), + TimeoutIn: new(5 * time.Minute), }, }, { @@ -219,7 +218,7 @@ func Test_EvaluateFirewallStatus(t *testing.T) { want: &FirewallStatusEvalResult{ Result: FirewallStatusProgressing, Reason: "not all health conditions are true: [Provisioned]", - TimeoutIn: pointer.Pointer(5 * time.Minute), + TimeoutIn: new(5 * time.Minute), }, }, } diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index 393c86c..aa288a2 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -495,6 +495,11 @@ func (in *FirewallNetwork) DeepCopyInto(out *FirewallNetwork) { *out = new(int64) **out = **in } + if in.Project != nil { + in, out := &in.Project, &out.Project + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirewallNetwork. diff --git a/config/crds/firewall.metal-stack.io_firewalldeployments.yaml b/config/crds/firewall.metal-stack.io_firewalldeployments.yaml index 411bf6a..1ea1570 100644 --- a/config/crds/firewall.metal-stack.io_firewalldeployments.yaml +++ b/config/crds/firewall.metal-stack.io_firewalldeployments.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.20.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: firewalldeployments.firewall.metal-stack.io spec: group: firewall.metal-stack.io diff --git a/config/crds/firewall.metal-stack.io_firewallmonitors.yaml b/config/crds/firewall.metal-stack.io_firewallmonitors.yaml index 637536b..f94ceb5 100644 --- a/config/crds/firewall.metal-stack.io_firewallmonitors.yaml +++ b/config/crds/firewall.metal-stack.io_firewallmonitors.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.20.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: firewallmonitors.firewall.metal-stack.io spec: group: firewall.metal-stack.io diff --git a/config/crds/firewall.metal-stack.io_firewalls.yaml b/config/crds/firewall.metal-stack.io_firewalls.yaml index 6087ab1..d70055d 100644 --- a/config/crds/firewall.metal-stack.io_firewalls.yaml +++ b/config/crds/firewall.metal-stack.io_firewalls.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.20.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: firewalls.firewall.metal-stack.io spec: group: firewall.metal-stack.io @@ -325,6 +325,9 @@ spec: items: type: string type: array + project: + description: Project of this network + type: string vrf: description: Vrf is vrf id of this network. format: int64 diff --git a/config/crds/firewall.metal-stack.io_firewallsets.yaml b/config/crds/firewall.metal-stack.io_firewallsets.yaml index 1f2b813..263e54e 100644 --- a/config/crds/firewall.metal-stack.io_firewallsets.yaml +++ b/config/crds/firewall.metal-stack.io_firewallsets.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.20.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: firewallsets.firewall.metal-stack.io spec: group: firewall.metal-stack.io diff --git a/controllers/firewall/controller.go b/controllers/firewall/controller.go index 1d1879a..7e8a72f 100644 --- a/controllers/firewall/controller.go +++ b/controllers/firewall/controller.go @@ -2,9 +2,7 @@ package firewall import ( "context" - "errors" "fmt" - "net/http" "time" "github.com/go-logr/logr" @@ -13,14 +11,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/predicate" + "github.com/metal-stack/api/go/errorutil" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/api/v2/config" "github.com/metal-stack/firewall-controller-manager/api/v2/defaults" "github.com/metal-stack/firewall-controller-manager/api/v2/validation" "github.com/metal-stack/firewall-controller-manager/controllers" - "github.com/metal-stack/metal-go/api/client/firewall" - "github.com/metal-stack/metal-go/api/client/network" - "github.com/metal-stack/metal-go/api/models" "github.com/metal-stack/metal-lib/pkg/cache" ) @@ -28,8 +25,8 @@ type controller struct { c *config.ControllerConfig log logr.Logger recorder events.EventRecorder - networkCache *cache.Cache[string, *models.V1NetworkResponse] - firewallCache *cache.Cache[*v2.Firewall, []*models.V1FirewallResponse] + networkCache *cache.Cache[string, *apiv2.Network] + firewallCache *cache.Cache[*v2.Firewall, []*apiv2.Machine] } func SetupWithManager(log logr.Logger, recorder events.EventRecorder, mgr ctrl.Manager, c *config.ControllerConfig) error { @@ -37,26 +34,32 @@ func SetupWithManager(log logr.Logger, recorder events.EventRecorder, mgr ctrl.M log: log, recorder: recorder, c: c, - networkCache: cache.New(5*time.Minute, func(ctx context.Context, id string) (*models.V1NetworkResponse, error) { - resp, err := c.GetMetal().Network().FindNetwork(network.NewFindNetworkParams().WithID(id).WithContext(ctx), nil) + networkCache: cache.New(5*time.Minute, func(ctx context.Context, id string) (*apiv2.Network, error) { + resp, err := c.GetMetal().Apiv2().Network().Get(ctx, &apiv2.NetworkServiceGetRequest{Project: c.GetProject(), Id: id}) if err != nil { return nil, fmt.Errorf("network find error: %w", err) } - return resp.Payload, nil + return resp.Network, nil }), // the cache is only very short but on quickly repeated status updates, this should prevent the metal-api from being flooded - firewallCache: cache.New(5*time.Second, func(ctx context.Context, fw *v2.Firewall) ([]*models.V1FirewallResponse, error) { - searchFirewalls := func() ([]*models.V1FirewallResponse, error) { - resp, err := c.GetMetal().Firewall().FindFirewalls(firewall.NewFindFirewallsParams().WithBody(&models.V1FirewallFindRequest{ - AllocationName: fw.Name, - AllocationProject: fw.Spec.Project, - Tags: []string{c.GetClusterTag()}, - }).WithContext(ctx), nil) + firewallCache: cache.New(5*time.Second, func(ctx context.Context, fw *v2.Firewall) ([]*apiv2.Machine, error) { + searchFirewalls := func() ([]*apiv2.Machine, error) { + resp, err := c.GetMetal().Apiv2().Machine().List(ctx, &apiv2.MachineServiceListRequest{ + Project: c.GetProject(), + Query: &apiv2.MachineQuery{ + Allocation: &apiv2.MachineAllocationQuery{ + Name: &fw.Name, + Labels: &apiv2.Labels{ + Labels: controllers.ToLabels([]string{c.GetClusterTag()}), + }, + }, + }, + }) if err != nil { return nil, fmt.Errorf("firewall search error: %w", err) } - return resp.Payload, nil + return resp.Machines, nil } // First try to find the firewall by machineID but check that allocation, project and hostname still matches @@ -66,20 +69,20 @@ func SetupWithManager(log logr.Logger, recorder events.EventRecorder, mgr ctrl.M // big enough that we agreed to do it. We still need to run the expensive lookup in the metal-api in case deriving // the machine from the status field does not work. if fw.Status.MachineStatus != nil && fw.Status.MachineStatus.MachineID != "" { - resp, err := c.GetMetal().Firewall().FindFirewall(firewall.NewFindFirewallParams().WithContext(ctx).WithID(fw.Status.MachineStatus.MachineID), nil) + resp, err := c.GetMetal().Apiv2().Machine().Get(ctx, &apiv2.MachineServiceGetRequest{Project: c.GetProject(), Uuid: fw.Status.MachineStatus.MachineID}) if err != nil { - var defaultErr *firewall.FindFirewallDefault - if errors.As(err, &defaultErr) && defaultErr.Code() == http.StatusNotFound { + + if errorutil.IsNotFound(err) { return searchFirewalls() } return nil, fmt.Errorf("firewall find error: %w", err) } - if resp.Payload.Allocation != nil && - *resp.Payload.Allocation.Project == fw.Spec.Project && - *resp.Payload.Allocation.Hostname == fw.Name { - return []*models.V1FirewallResponse{resp.Payload}, nil + if resp.Machine.Allocation != nil && + resp.Machine.Allocation.Project == fw.Spec.Project && + resp.Machine.Allocation.Hostname == fw.Name { + return []*apiv2.Machine{resp.Machine}, nil } } diff --git a/controllers/firewall/delete.go b/controllers/firewall/delete.go index 20f1de1..7d29a1a 100644 --- a/controllers/firewall/delete.go +++ b/controllers/firewall/delete.go @@ -5,9 +5,9 @@ import ( "fmt" "time" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/controllers" - "github.com/metal-stack/metal-go/api/client/machine" apierrors "k8s.io/apimachinery/pkg/api/errors" corev1 "k8s.io/api/core/v1" @@ -35,20 +35,19 @@ func (c *controller) Delete(r *controllers.Ctx[*v2.Firewall]) error { } for _, f := range fws { - if f.ID == nil { - continue - } - - resp, err := c.c.GetMetal().Machine().FreeMachine(machine.NewFreeMachineParams().WithID(*f.ID).WithContext(r.Ctx), nil) + resp, err := c.c.GetMetal().Apiv2().Machine().Delete(r.Ctx, &apiv2.MachineServiceDeleteRequest{ + Uuid: f.Uuid, + Project: c.c.GetProject(), + }) if err != nil { r.Log.Error(err, "firewall deletion failed") return controllers.RequeueAfter(5*time.Second, "firewall deletion failed, retrying") } - r.Log.Info("deleted firewall", "firewall-name", f.Name, "id", *resp.Payload.ID) + r.Log.Info("deleted firewall", "firewall-name", f.Allocation.Name, "id", resp.Machine.Uuid) - c.recorder.Eventf(r.Target, nil, corev1.EventTypeNormal, "Delete", "deleting firewall", "deleted firewall %s id %s", r.Target.Name, *resp.Payload.ID) + c.recorder.Eventf(r.Target, nil, corev1.EventTypeNormal, "Delete", "deleting firewall", "deleted firewall %s id %s", r.Target.Name, resp.Machine.Uuid) } return nil diff --git a/controllers/firewall/reconcile.go b/controllers/firewall/reconcile.go index b58d85c..cf3185b 100644 --- a/controllers/firewall/reconcile.go +++ b/controllers/firewall/reconcile.go @@ -6,12 +6,12 @@ import ( "strings" "time" + "github.com/metal-stack/api/go/enum" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/controllers" - "github.com/metal-stack/metal-go/api/client/firewall" - "github.com/metal-stack/metal-go/api/client/machine" - "github.com/metal-stack/metal-go/api/models" "github.com/metal-stack/metal-lib/pkg/pointer" + "google.golang.org/protobuf/reflect/protoreflect" "sigs.k8s.io/controller-runtime/pkg/client" corev1 "k8s.io/api/core/v1" @@ -48,7 +48,7 @@ func (c *controller) Reconcile(r *controllers.Ctx[*v2.Firewall]) error { return controllers.RequeueAfter(0*time.Second, "removed systemd service restart annotation, requeue for regular reconcile") } - var f *models.V1FirewallResponse + var f *apiv2.Machine defer func() { if err := c.setStatus(r, f); err != nil { r.Log.Error(err, "unable to set firewall status") @@ -81,7 +81,7 @@ func (c *controller) Reconcile(r *controllers.Ctx[*v2.Firewall]) error { case 1: f = fws[0] - cond := v2.NewCondition(v2.FirewallCreated, v2.ConditionTrue, "Created", fmt.Sprintf("Firewall %q created successfully.", pointer.SafeDeref(pointer.SafeDeref(f.Allocation).Name))) + cond := v2.NewCondition(v2.FirewallCreated, v2.ConditionTrue, "Created", fmt.Sprintf("Firewall %q created successfully.", pointer.SafeDeref(f.Allocation).Name)) r.Target.Status.Conditions.Set(cond) // this is mainly for tests when the firewall is already present @@ -98,9 +98,9 @@ func (c *controller) Reconcile(r *controllers.Ctx[*v2.Firewall]) error { if isFirewallReady(currentStatus) { - r.Log.Info("firewall reconciled successfully", "id", pointer.SafeDeref(f.ID)) + r.Log.Info("firewall reconciled successfully", "id", f.Uuid) - cond := v2.NewCondition(v2.FirewallReady, v2.ConditionTrue, "Ready", fmt.Sprintf("Firewall %q is phoning home and alive.", pointer.SafeDeref(pointer.SafeDeref(f.Allocation).Name))) + cond := v2.NewCondition(v2.FirewallReady, v2.ConditionTrue, "Ready", fmt.Sprintf("Firewall %q is phoning home and alive.", pointer.SafeDeref(f.Allocation).Name)) r.Target.Status.Conditions.Set(cond) r.Target.Status.Phase = v2.FirewallPhaseRunning @@ -115,27 +115,27 @@ func (c *controller) Reconcile(r *controllers.Ctx[*v2.Firewall]) error { return controllers.RequeueAfter(10*time.Second, "error syncing firewall ssh keys, backing off") } - // to make the controller always sync the status with the metal-api, we requeue + // to make the controller always sync the status with the metal-apiserver, we requeue return controllers.RequeueAfter(2*time.Minute, "firewall is running, continue probing regularly for status sync") } else if isFirewallProgressing(currentStatus) { - r.Log.Info("firewall is progressing", "id", pointer.SafeDeref(f.ID)) + r.Log.Info("firewall is progressing", "id", f.Uuid) - cond := v2.NewCondition(v2.FirewallReady, v2.ConditionFalse, "NotReady", fmt.Sprintf("Firewall %q is not ready.", pointer.SafeDeref(pointer.SafeDeref(f.Allocation).Name))) + cond := v2.NewCondition(v2.FirewallReady, v2.ConditionFalse, "NotReady", fmt.Sprintf("Firewall %q is not ready.", pointer.SafeDeref(f.Allocation).Name)) r.Target.Status.Conditions.Set(cond) return controllers.RequeueAfter(10*time.Second, "firewall creation is progressing") } else { - r.Log.Error(fmt.Errorf("firewall is not finishing the provisioning"), "please investigate", "id", pointer.SafeDeref(f.ID)) + r.Log.Error(fmt.Errorf("firewall is not finishing the provisioning"), "please investigate", "id", f.Uuid) if pointer.SafeDeref(currentStatus).CrashLoop { r.Target.Status.Phase = v2.FirewallPhaseCrashing } - cond := v2.NewCondition(v2.FirewallReady, v2.ConditionFalse, "NotFinishing", fmt.Sprintf("Firewall %q is not finishing the provisioning procedure.", pointer.SafeDeref(pointer.SafeDeref(f.Allocation).Name))) + cond := v2.NewCondition(v2.FirewallReady, v2.ConditionFalse, "NotFinishing", fmt.Sprintf("Firewall %q is not finishing the provisioning procedure.", pointer.SafeDeref(f.Allocation).Name)) r.Target.Status.Conditions.Set(cond) return controllers.RequeueAfter(1*time.Minute, "firewall creation is not finishing, proceed probing") @@ -144,7 +144,7 @@ func (c *controller) Reconcile(r *controllers.Ctx[*v2.Firewall]) error { default: var ids []string for _, fw := range fws { - ids = append(ids, pointer.SafeDeref(fw.ID)) + ids = append(ids, fw.Uuid) } cond := v2.NewCondition(v2.FirewallCreated, v2.ConditionFalse, "MultipleFirewalls", fmt.Sprintf("Found multiple firewalls with the same name: %s", strings.Join(ids, ", "))) @@ -154,18 +154,17 @@ func (c *controller) Reconcile(r *controllers.Ctx[*v2.Firewall]) error { } } -func (c *controller) createFirewall(r *controllers.Ctx[*v2.Firewall]) (*models.V1FirewallResponse, error) { +func (c *controller) createFirewall(r *controllers.Ctx[*v2.Firewall]) (*apiv2.Machine, error) { var ( - networks []*models.V1MachineAllocationNetwork + networks []*apiv2.MachineAllocationNetwork tags = []string{ c.c.GetClusterTag(), v2.FirewallManagedByTag(), } ) for _, n := range r.Target.Spec.Networks { - network := &models.V1MachineAllocationNetwork{ - Networkid: &n, - Autoacquire: new(true), + network := &apiv2.MachineAllocationNetwork{ + Network: n, } networks = append(networks, network) } @@ -175,21 +174,24 @@ func (c *controller) createFirewall(r *controllers.Ctx[*v2.Firewall]) (*models.V tags = append(tags, v2.FirewallSetTag(ref.Name)) } - createRequest := &models.V1FirewallCreateRequest{ - Description: "created by firewall-controller-manager", - Name: r.Target.Name, - Hostname: r.Target.Name, - Sizeid: &r.Target.Spec.Size, - Projectid: &r.Target.Spec.Project, - Partitionid: &r.Target.Spec.Partition, - Imageid: &r.Target.Spec.Image, - SSHPubKeys: r.Target.Spec.SSHPublicKeys, - Networks: networks, - UserData: r.Target.Spec.Userdata, - Tags: tags, + createRequest := &apiv2.MachineServiceCreateRequest{ + Project: r.Target.Spec.Project, + Name: r.Target.Name, + Hostname: &r.Target.Name, + Description: new("created by firewall-controller-manager"), + Size: &r.Target.Spec.Size, + Partition: &r.Target.Spec.Partition, + Image: r.Target.Spec.Image, + SshPublicKeys: r.Target.Spec.SSHPublicKeys, + Networks: networks, + Userdata: &r.Target.Spec.Userdata, + AllocationType: apiv2.MachineAllocationType_MACHINE_ALLOCATION_TYPE_FIREWALL, + Labels: &apiv2.Labels{ + Labels: controllers.ToLabels(tags), + }, } - resp, err := c.c.GetMetal().Firewall().AllocateFirewall(firewall.NewAllocateFirewallParams().WithBody(createRequest).WithContext(r.Ctx), nil) + resp, err := c.c.GetMetal().Apiv2().Machine().Create(r.Ctx, createRequest) if err != nil { r.Log.Error(err, "error creating firewall") @@ -199,14 +201,14 @@ func (c *controller) createFirewall(r *controllers.Ctx[*v2.Firewall]) (*models.V return nil, controllers.RequeueAfter(30*time.Second, "error creating firewall, backing off") } - r.Log.Info("firewall created", "id", pointer.SafeDeref(resp.Payload.ID)) + r.Log.Info("firewall created", "id", resp.Machine.Uuid) - cond := v2.NewCondition(v2.FirewallCreated, v2.ConditionTrue, "Created", fmt.Sprintf("Firewall %q created successfully.", pointer.SafeDeref(pointer.SafeDeref(resp.Payload.Allocation).Name))) + cond := v2.NewCondition(v2.FirewallCreated, v2.ConditionTrue, "Created", fmt.Sprintf("Firewall %q created successfully.", pointer.SafeDeref(resp.Machine.Allocation).Name)) r.Target.Status.Conditions.Set(cond) - c.recorder.Eventf(r.Target, nil, corev1.EventTypeNormal, "Create", "created firewall %s id %s", r.Target.Name, pointer.SafeDeref(resp.Payload.ID)) + c.recorder.Eventf(r.Target, nil, corev1.EventTypeNormal, "Create", "created firewall %s id %s", r.Target.Name, resp.Machine.Uuid) - return resp.Payload, nil + return resp.Machine, nil } func isFirewallProgressing(status *v2.MachineStatus) bool { @@ -216,12 +218,10 @@ func isFirewallProgressing(status *v2.MachineStatus) bool { if status.CrashLoop { return false } - // TODO replace with models.V1LivelinessAlive once merged - if status.Liveliness != "Alive" { + if status.Liveliness != mustStringValue(apiv2.MachineLiveliness_MACHINE_LIVELINESS_ALIVE) { return false } - // TODO replace with models.V1LivelinessPhonedHome once merged - if status.LastEvent.Event != "Phoned Home" { + if status.LastEvent.Event != mustStringValue(apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_PHONED_HOME) { return true } @@ -235,37 +235,53 @@ func isFirewallReady(status *v2.MachineStatus) bool { if status.CrashLoop { return false } - // TODO replace with models.V1LivelinessAlive once merged - if status.Liveliness != "Alive" { + if status.Liveliness != mustStringValue(apiv2.MachineLiveliness_MACHINE_LIVELINESS_ALIVE) { return false } - // TODO replace with models.V1LivelinessPhonedHome once merged - if status.LastEvent.Event == "Phoned Home" { + if status.LastEvent.Event == mustStringValue(apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_PHONED_HOME) { return true } return false } -func (c *controller) syncTags(r *controllers.Ctx[*v2.Firewall], m *models.V1FirewallResponse) error { +func mustStringValue[E protoreflect.Enum](e E) string { + val, err := enum.GetStringValue(e) + if err != nil { + panic(err) + } + + return *val +} + +func (c *controller) syncTags(r *controllers.Ctx[*v2.Firewall], m *apiv2.Machine) error { + var ( newTags []string ref = metav1.GetControllerOf(r.Target) ) - newTags = ensureTag(m.Tags, v2.FirewallControllerManagedByAnnotation, v2.FirewallControllerManager) + mtags := controllers.ToTags(pointer.SafeDeref(pointer.SafeDeref(m.Meta).Labels).Labels) + + newTags = ensureTag(mtags, v2.FirewallControllerManagedByAnnotation, v2.FirewallControllerManager) if ref != nil { newTags = ensureTag(newTags, v2.FirewallControllerSetAnnotation, ref.Name) } - if sets.NewString(newTags...).Equal(sets.NewString(m.Tags...)) { + if sets.NewString(newTags...).Equal(sets.NewString(mtags...)) { return nil } - _, err := c.c.GetMetal().Machine().UpdateMachine(machine.NewUpdateMachineParams().WithBody(&models.V1MachineUpdateRequest{ - ID: m.ID, - Tags: newTags, - }).WithContext(r.Ctx), nil) + _, err := c.c.GetMetal().Apiv2().Machine().Update(r.Ctx, &apiv2.MachineServiceUpdateRequest{ + Uuid: m.Uuid, + Labels: &apiv2.UpdateLabels{ + Strategy: &apiv2.UpdateLabels_Replace{ + Replace: &apiv2.Labels{ + Labels: controllers.ToLabels(newTags), + }, + }, + }, + }) if err != nil { return err } @@ -303,19 +319,20 @@ func ensureTag(currentTags []string, key, value string) []string { return newTags } -func (c *controller) syncSSHPubKey(r *controllers.Ctx[*v2.Firewall], m *models.V1FirewallResponse) error { +func (c *controller) syncSSHPubKey(r *controllers.Ctx[*v2.Firewall], m *apiv2.Machine) error { if m.Allocation == nil { return fmt.Errorf("firewall has no allocation in metal-api") } - if slices.Equal(m.Allocation.SSHPubKeys, r.Target.Spec.SSHPublicKeys) { + if slices.Equal(m.Allocation.SshPublicKeys, r.Target.Spec.SSHPublicKeys) { return nil } - _, err := c.c.GetMetal().Machine().UpdateMachine(machine.NewUpdateMachineParams().WithBody(&models.V1MachineUpdateRequest{ - ID: m.ID, - SSHPubKeys: r.Target.Spec.SSHPublicKeys, - }).WithContext(r.Ctx), nil) + _, err := c.c.GetMetal().Apiv2().Machine().Update(r.Ctx, &apiv2.MachineServiceUpdateRequest{ + Uuid: m.Uuid, + Project: c.c.GetProject(), + SshPublicKeys: r.Target.Spec.SSHPublicKeys, + }) if err != nil { return fmt.Errorf("unable to update ssh public keys: %w", err) } diff --git a/controllers/firewall/status.go b/controllers/firewall/status.go index 38a1e09..bab76d0 100644 --- a/controllers/firewall/status.go +++ b/controllers/firewall/status.go @@ -5,14 +5,14 @@ import ( "fmt" "time" + "github.com/metal-stack/api/go/enum" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/controllers" - "github.com/metal-stack/metal-go/api/models" - "github.com/metal-stack/metal-lib/pkg/pointer" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (c *controller) setStatus(r *controllers.Ctx[*v2.Firewall], f *models.V1FirewallResponse) error { +func (c *controller) setStatus(r *controllers.Ctx[*v2.Firewall], f *apiv2.Machine) error { var errs []error err := setMachineStatus(r.Target, f) @@ -30,7 +30,7 @@ func (c *controller) setStatus(r *controllers.Ctx[*v2.Firewall], f *models.V1Fir return errors.Join(errs...) } -func setMachineStatus(fw *v2.Firewall, f *models.V1FirewallResponse) error { +func setMachineStatus(fw *v2.Firewall, f *apiv2.Machine) error { if f == nil { return nil } @@ -45,35 +45,44 @@ func setMachineStatus(fw *v2.Firewall, f *models.V1FirewallResponse) error { return nil } -func getMachineStatus(f *models.V1FirewallResponse) (*v2.MachineStatus, error) { - if f.ID == nil || f.Allocation == nil || f.Allocation.Created == nil || f.Liveliness == nil || f.Allocation.Image == nil { +func getMachineStatus(f *apiv2.Machine) (*v2.MachineStatus, error) { + if f.Allocation == nil || f.Allocation.Meta == nil || f.Allocation.Meta.CreatedAt == nil || f.Allocation.Image == nil || f.Status == nil { return nil, fmt.Errorf("firewall entity from metal-api is missing essential fields") } + liveliness, err := enum.GetStringValue(f.Status.Liveliness) + if err != nil { + return nil, err + } + result := &v2.MachineStatus{ - MachineID: *f.ID, - AllocationTimestamp: metav1.NewTime(time.Time(*f.Allocation.Created)), - Liveliness: *f.Liveliness, - ImageID: pointer.SafeDeref(f.Allocation.Image.ID), + MachineID: f.Uuid, + AllocationTimestamp: metav1.NewTime(f.Allocation.Meta.CreatedAt.AsTime()), + Liveliness: *liveliness, + ImageID: f.Allocation.Image.Id, } - if f.Events != nil && f.Events.CrashLoop != nil { - result.CrashLoop = *f.Events.CrashLoop + if f.RecentProvisioningEvents != nil && f.RecentProvisioningEvents.State == apiv2.MachineProvisioningEventState_MACHINE_PROVISIONING_EVENT_STATE_CRASHLOOP { + result.CrashLoop = true } - if f.Events != nil && len(f.Events.Log) > 0 && f.Events.Log[0].Event != nil { - log := f.Events.Log[0] + if f.RecentProvisioningEvents != nil && len(f.RecentProvisioningEvents.Events) > 0 { + event := f.RecentProvisioningEvents.Events[0] + eventType, err := enum.GetStringValue(event.Event) + if err != nil { + return nil, err + } result.LastEvent = &v2.MachineLastEvent{ - Event: *log.Event, - Timestamp: metav1.NewTime(time.Time(log.Time)), - Message: log.Message, + Event: *eventType, + Timestamp: metav1.NewTime(event.Time.AsTime()), + Message: event.Message, } } return result, nil } -func (c *controller) setFirewallNetworks(r *controllers.Ctx[*v2.Firewall], f *models.V1FirewallResponse) error { +func (c *controller) setFirewallNetworks(r *controllers.Ctx[*v2.Firewall], f *apiv2.Machine) error { // check whether network prefixes were updated in metal-api // prefixes in the firewall machine allocation are just a snapshot when the firewall was created. // -> when changing prefixes in the referenced network the firewall does not know about any prefix changes. @@ -92,24 +101,29 @@ func (c *controller) setFirewallNetworks(r *controllers.Ctx[*v2.Firewall], f *mo var result []v2.FirewallNetwork for _, n := range f.Allocation.Networks { - if n.Networkid == nil { - continue + nw, err := c.networkCache.Get(r.Ctx, n.Network) + if err != nil { + return err } - - nw, err := c.networkCache.Get(r.Ctx, *n.Networkid) + networkType, err := enum.GetStringValue(n.NetworkType) if err != nil { return err } + var nat bool + if n.NatType == apiv2.NATType_NAT_TYPE_IPV4_MASQUERADE { + nat = true + } result = append(result, v2.FirewallNetwork{ - ASN: n.Asn, - DestinationPrefixes: n.Destinationprefixes, + ASN: new(int64(n.Asn)), + DestinationPrefixes: n.DestinationPrefixes, IPs: n.Ips, - Nat: n.Nat, - NetworkID: n.Networkid, - NetworkType: n.Networktype, + Nat: &nat, + NetworkID: &n.Network, + NetworkType: networkType, Prefixes: nw.Prefixes, - Vrf: n.Vrf, + Vrf: new(int64(n.Vrf)), + Project: n.Project, }) } diff --git a/controllers/set/suite_test.go b/controllers/set/suite_test.go index 85971fe..fc12fdf 100644 --- a/controllers/set/suite_test.go +++ b/controllers/set/suite_test.go @@ -13,7 +13,7 @@ import ( "github.com/metal-stack/firewall-controller-manager/controllers" "github.com/metal-stack/firewall-controller-manager/controllers/firewall" "github.com/metal-stack/firewall-controller-manager/controllers/set" - metalclient "github.com/metal-stack/metal-go/test/client" + "github.com/metal-stack/firewall-controller-manager/internal/test" "github.com/metal-stack/metal-lib/pkg/tag" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -93,7 +93,7 @@ var _ = BeforeSuite(func() { }) Expect(err).ToNot(HaveOccurred()) - _, metalClient := metalclient.NewMetalMockClient(testingT, &metalclient.MetalMockFns{}) + metalClient := test.New(testingT).Client() cc, err := controllerconfig.New(&controllerconfig.NewControllerConfig{ SeedClient: k8sClient, diff --git a/controllers/tags.go b/controllers/tags.go new file mode 100644 index 0000000..16ff582 --- /dev/null +++ b/controllers/tags.go @@ -0,0 +1,25 @@ +package controllers + +import ( + "fmt" + "strings" +) + +// ToLabels constructs a map of a list of labels. +func ToLabels(tags []string) map[string]string { + result := map[string]string{} + for _, l := range tags { + key, value, _ := strings.Cut(l, "=") + result[key] = value + } + return result +} + +// ToLabels constructs a list of labels. +func ToTags(labels map[string]string) []string { + result := []string{} + for k, v := range labels { + result = append(result, fmt.Sprintf("%s=%s", k, v)) + } + return result +} diff --git a/controllers/update/controller.go b/controllers/update/controller.go index 6d78cf5..4f54353 100644 --- a/controllers/update/controller.go +++ b/controllers/update/controller.go @@ -10,12 +10,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/predicate" + apiv2client "github.com/metal-stack/api/go/client" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/api/v2/config" "github.com/metal-stack/firewall-controller-manager/controllers" - metalgo "github.com/metal-stack/metal-go" - "github.com/metal-stack/metal-go/api/client/image" - "github.com/metal-stack/metal-go/api/models" "github.com/metal-stack/metal-lib/pkg/cache" ) @@ -23,7 +22,7 @@ type controller struct { c *config.ControllerConfig log logr.Logger recorder events.EventRecorder - imageCache *cache.Cache[string, *models.V1ImageResponse] + imageCache *cache.Cache[string, *apiv2.Image] } func SetupWithManager(log logr.Logger, recorder events.EventRecorder, mgr ctrl.Manager, c *config.ControllerConfig) error { @@ -56,13 +55,13 @@ func (c *controller) Delete(_ *controllers.Ctx[*v2.FirewallDeployment]) error { return nil } -func newImageCache(m metalgo.Client) *cache.Cache[string, *models.V1ImageResponse] { - return cache.New(5*time.Minute, func(ctx context.Context, id string) (*models.V1ImageResponse, error) { - resp, err := m.Image().FindLatestImage(image.NewFindLatestImageParams().WithID(id).WithContext(ctx), nil) +func newImageCache(m apiv2client.Client) *cache.Cache[string, *apiv2.Image] { + return cache.New(5*time.Minute, func(ctx context.Context, id string) (*apiv2.Image, error) { + resp, err := m.Apiv2().Image().Latest(ctx, &apiv2.ImageServiceLatestRequest{Os: id}) if err != nil { return nil, err } - return resp.Payload, nil + return resp.Image, nil }) } diff --git a/controllers/update/reconcile.go b/controllers/update/reconcile.go index dd08c99..01bff33 100644 --- a/controllers/update/reconcile.go +++ b/controllers/update/reconcile.go @@ -48,7 +48,7 @@ func (c *controller) autoUpdateOS(r *controllers.Ctx[*v2.FirewallDeployment]) er return fmt.Errorf("unable to retrieve latest os image from metal-api: %w", err) } - if image.ID == nil { + if image.Id == "" { return fmt.Errorf("returned image from metal-api contains no id") } @@ -89,7 +89,7 @@ func (c *controller) autoUpdateOS(r *controllers.Ctx[*v2.FirewallDeployment]) er // finally, we can do the image comparison - if *image.ID == fw.Status.MachineStatus.ImageID { + if image.Id == fw.Status.MachineStatus.ImageID { r.Log.Info("no new os version available, not triggering auto-update") return nil } @@ -109,7 +109,7 @@ func (c *controller) autoUpdateOS(r *controllers.Ctx[*v2.FirewallDeployment]) er refetched.Annotations[v2.RollSetAnnotation] = strconv.FormatBool(true) if isFullyQualifiedImageNotation { - refetched.Spec.Template.Spec.Image = *image.ID + refetched.Spec.Template.Spec.Image = image.Id } err = c.c.GetSeedClient().Update(r.Ctx, refetched) diff --git a/controllers/update/reconcile_test.go b/controllers/update/reconcile_test.go index 635a020..115c138 100644 --- a/controllers/update/reconcile_test.go +++ b/controllers/update/reconcile_test.go @@ -7,15 +7,13 @@ import ( "github.com/go-logr/logr" "github.com/google/go-cmp/cmp" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/api/v2/config" "github.com/metal-stack/firewall-controller-manager/controllers" - "github.com/metal-stack/metal-go/api/client/image" - "github.com/metal-stack/metal-go/api/models" - metaltestclient "github.com/metal-stack/metal-go/test/client" + "github.com/metal-stack/firewall-controller-manager/internal/test" "github.com/metal-stack/metal-lib/pkg/testcommon" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -31,7 +29,7 @@ func Test_controller_autoUpdateOS(t *testing.T) { tests := []struct { name string - metalMocks *metaltestclient.MetalMockFns + latestImage *apiv2.Image fwDeploy *v2.FirewallDeployment existingFws []v2.Firewall postTestFn func(t *testing.T, c client.Client) @@ -109,14 +107,8 @@ func Test_controller_autoUpdateOS(t *testing.T) { }, }, withinMaintenance: true, - metalMocks: &metaltestclient.MetalMockFns{ - Image: func(mock *mock.Mock) { - mock.On("FindLatestImage", image.NewFindLatestImageParams().WithID("firewall-ubuntu-3.0").WithContext(ctx), nil).Return(&image.FindLatestImageOK{ - Payload: &models.V1ImageResponse{ - ID: new("firewall-ubuntu-3.0.20240503"), - }, - }, nil) - }, + latestImage: &apiv2.Image{ + Id: "firewall-ubuntu-3.0.20240503", }, existingFws: []v2.Firewall{ { @@ -165,14 +157,8 @@ func Test_controller_autoUpdateOS(t *testing.T) { }, }, withinMaintenance: true, - metalMocks: &metaltestclient.MetalMockFns{ - Image: func(mock *mock.Mock) { - mock.On("FindLatestImage", image.NewFindLatestImageParams().WithID("firewall-ubuntu-3.0").WithContext(ctx), nil).Return(&image.FindLatestImageOK{ - Payload: &models.V1ImageResponse{ - ID: new("firewall-ubuntu-3.0.20240503"), - }, - }, nil) - }, + latestImage: &apiv2.Image{ + Id: "firewall-ubuntu-3.0.20240503", }, existingFws: []v2.Firewall{ { @@ -205,7 +191,10 @@ func Test_controller_autoUpdateOS(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, mc := metaltestclient.NewMetalMockClient(t, tt.metalMocks) + mm := test.New(t) + mm.OnImageLatest = func(_ context.Context, _ *apiv2.ImageServiceLatestRequest) (*apiv2.ImageServiceLatestResponse, error) { + return &apiv2.ImageServiceLatestResponse{Image: tt.latestImage}, nil + } latestSet := v2.FirewallSet{ ObjectMeta: metav1.ObjectMeta{ @@ -238,7 +227,7 @@ func Test_controller_autoUpdateOS(t *testing.T) { c := &controller{ c: cc, - imageCache: newImageCache(mc), + imageCache: newImageCache(mm.Client()), } r := &controllers.Ctx[*v2.FirewallDeployment]{ diff --git a/go.mod b/go.mod index feb936b..25bee89 100644 --- a/go.mod +++ b/go.mod @@ -3,19 +3,20 @@ module github.com/metal-stack/firewall-controller-manager go 1.26 require ( - github.com/Masterminds/semver/v3 v3.4.0 + connectrpc.com/connect v1.20.0 + github.com/Masterminds/semver/v3 v3.5.0 github.com/flatcar/container-linux-config-transpiler v0.9.4 - github.com/go-logr/logr v1.4.3 - github.com/go-openapi/strfmt v0.25.0 + github.com/go-logr/logr v1.4.4 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 - github.com/metal-stack/metal-go v0.42.5 - github.com/metal-stack/metal-lib v0.23.5 + github.com/metal-stack/api v0.4.4 + github.com/metal-stack/metal-lib v0.26.1 github.com/metal-stack/v v1.0.3 - github.com/onsi/ginkgo/v2 v2.27.5 - github.com/onsi/gomega v1.39.0 - github.com/prometheus/client_golang v1.23.2 + github.com/onsi/ginkgo/v2 v2.32.0 + github.com/onsi/gomega v1.42.1 + github.com/prometheus/client_golang v1.24.1 github.com/stretchr/testify v1.11.1 + google.golang.org/protobuf v1.36.11 k8s.io/api v0.35.0 k8s.io/apimachinery v0.35.0 k8s.io/client-go v0.35.0 @@ -23,114 +24,100 @@ require ( ) require ( + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260709200747-435963d16310.1 // indirect + buf.build/go/protovalidate v1.2.0 // indirect + buf.build/go/protoyaml v0.7.0 // indirect + cel.dev/expr v0.25.2 // indirect github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 // indirect - github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/coreos/go-oidc/v3 v3.14.1 // indirect + github.com/clipperhouse/displaywidth v0.10.0 // indirect + github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect - github.com/fatih/color v1.18.0 // indirect + github.com/fatih/color v1.19.0 // indirect github.com/flatcar/ignition v0.36.2 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-jose/go-jose/v4 v4.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.4 // 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/swag v0.24.1 // indirect - github.com/go-openapi/swag/cmdutils v0.24.0 // indirect - github.com/go-openapi/swag/conv v0.24.0 // indirect - github.com/go-openapi/swag/fileutils v0.24.0 // indirect - github.com/go-openapi/swag/jsonname v0.24.0 // indirect - github.com/go-openapi/swag/jsonutils v0.24.0 // indirect - github.com/go-openapi/swag/loading v0.24.0 // indirect - github.com/go-openapi/swag/mangling v0.24.0 // indirect - github.com/go-openapi/swag/netutils v0.24.0 // indirect - github.com/go-openapi/swag/stringutils v0.24.0 // indirect - github.com/go-openapi/swag/typeutils v0.24.0 // indirect - github.com/go-openapi/swag/yamlutils v0.24.0 // indirect - github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-openapi/errors v0.22.8 // indirect + github.com/go-openapi/jsonpointer v1.0.0 // indirect + github.com/go-openapi/jsonreference v1.0.0 // indirect + github.com/go-openapi/strfmt v0.27.0 // indirect + github.com/go-openapi/swag v0.28.0 // indirect + github.com/go-openapi/swag/cmdutils v0.28.0 // indirect + github.com/go-openapi/swag/conv v0.28.0 // indirect + github.com/go-openapi/swag/fileutils v0.28.0 // indirect + github.com/go-openapi/swag/jsonutils v0.28.0 // indirect + github.com/go-openapi/swag/loading v0.28.0 // indirect + github.com/go-openapi/swag/mangling v0.28.0 // indirect + github.com/go-openapi/swag/netutils v0.28.0 // indirect + github.com/go-openapi/swag/pools v0.28.0 // indirect + github.com/go-openapi/swag/stringutils v0.28.0 // indirect + github.com/go-openapi/swag/typeutils v0.28.0 // indirect + github.com/go-openapi/swag/yamlutils v0.28.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect - github.com/goccy/go-json v0.10.5 // indirect - github.com/goccy/go-yaml v1.18.0 // indirect - github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect + github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/google/btree v1.1.3 // indirect + github.com/google/cel-go v0.30.0 // indirect github.com/google/gnostic-models v0.7.0 // indirect - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect - github.com/gorilla/mux v1.8.1 // indirect + github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/lestrrat-go/blackmagic v1.0.3 // indirect - github.com/lestrrat-go/httpcc v1.0.1 // indirect - github.com/lestrrat-go/httprc v1.0.6 // indirect - github.com/lestrrat-go/iter v1.0.2 // indirect - github.com/lestrrat-go/jwx/v2 v2.1.5 // indirect - github.com/lestrrat-go/option v1.0.1 // indirect - github.com/mailru/easyjson v0.9.0 // indirect + github.com/klauspost/compress v1.19.1 // indirect + github.com/klauspost/connect-compress/v2 v2.1.1 // 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/metal-stack/security v0.9.4 // indirect + github.com/mattn/go-isatty v0.0.21 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/minio/minlz v1.2.0 // 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/oklog/ulid v1.3.1 // indirect - github.com/olekukonko/errors v1.1.0 // indirect - github.com/olekukonko/ll v0.0.9 // indirect - github.com/olekukonko/tablewriter v1.0.8 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/oklog/ulid/v2 v2.1.1 // indirect + github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect + github.com/olekukonko/errors v1.2.0 // indirect + github.com/olekukonko/ll v0.1.6 // indirect + github.com/olekukonko/tablewriter v1.1.4 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.66.1 // indirect - github.com/prometheus/procfs v0.16.1 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/sagikazarmark/locafero v0.7.0 // indirect - github.com/segmentio/asm v1.2.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/cobra v1.10.0 // indirect - github.com/spf13/pflag v1.0.9 // indirect - github.com/spf13/viper v1.20.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect + github.com/prometheus/common v0.70.1 // indirect + github.com/prometheus/procfs v0.21.1 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/cobra v1.10.2 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spf13/viper v1.21.0 // indirect + github.com/stretchr/objx v0.5.3 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/vincent-petithory/dataurl v1.0.0 // indirect github.com/x448/float16 v0.8.4 // indirect - go.mongodb.org/mongo-driver v1.17.6 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel v1.36.0 // indirect - go.opentelemetry.io/otel/metric v1.36.0 // indirect - go.opentelemetry.io/otel/trace v1.36.0 // 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 + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/mod v0.32.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/term v0.39.0 // indirect - golang.org/x/text v0.33.0 // indirect - golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.41.0 // indirect + golang.org/x/exp v0.0.0-20260718201538-764159d718ef // indirect + golang.org/x/mod v0.38.0 // indirect + golang.org/x/net v0.57.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/term v0.45.0 // indirect + golang.org/x/text v0.40.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.48.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/protobuf v1.36.8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/grpc v1.83.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 9f43d72..0e58f04 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,11 @@ +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260709200747-435963d16310.1 h1:fXh8CsdNpjRr8R5vFdqtIxPt/Lno2IIJlYOdZBIZn0w= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260709200747-435963d16310.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM= +buf.build/go/protovalidate v1.2.0 h1:DQVrUWkmGTBij+kOYv/x2LLxwcLaGKMdzShj1/6/3H0= +buf.build/go/protovalidate v1.2.0/go.mod h1:7rYiQEhqvAipoazpVNBBH2S2f8bjG4huMVy1V2Yofn4= +buf.build/go/protoyaml v0.7.0 h1:z4oVoFicbpPefhT7WAykxUdfp0yEQlhMQ2mCZOY5V38= +buf.build/go/protoyaml v0.7.0/go.mod h1:+a0cavd0uMvirb87xdu2ZMMmjlIQoiH/N2Ich5MGSQ0= +cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= +cel.dev/expr v0.25.2/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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -14,20 +22,26 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ= +connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -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/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= +github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/ajeddeloh/go-json v0.0.0-20160803184958-73d058cf8437/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc= github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +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/aws/aws-sdk-go v1.8.39/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= 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/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -35,8 +49,10 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk= -github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU= +github.com/clipperhouse/displaywidth v0.10.0 h1:GhBG8WuerxjFQQYeuZAeVTuyxuX+UraiZGD4HJQ3Y8g= +github.com/clipperhouse/displaywidth v0.10.0/go.mod h1:XqJajYsaiEwkxOj4bowCTMcT1SgvHo9flfF3jQasdbs= +github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos= +github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/coreos/go-semver v0.1.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -49,8 +65,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= 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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -59,8 +73,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 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/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/flatcar/container-linux-config-transpiler v0.9.4 h1:yXQ0NB8PeNrKJPrZvbv5/DV63PNhTqt8vaf8YxmX/RA= github.com/flatcar/container-linux-config-transpiler v0.9.4/go.mod h1:LxanhPvXkWgHG9PrkT4rX/p7YhUPdDGGsUdkNpV3L5U= github.com/flatcar/ignition v0.36.2 h1:xGHgScUe0P4Fkprjqv7L2CE58emiQgP833OCCn9z2v4= @@ -80,70 +94,57 @@ github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiH github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY= -github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw= -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/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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.4 h1:oi2K9mHTOb5DPW2Zjdzs/NIvwi2N3fARKaTJLdNabaM= -github.com/go-openapi/errors v0.22.4/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= -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.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= -github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= -github.com/go-openapi/swag v0.24.1 h1:DPdYTZKo6AQCRqzwr/kGkxJzHhpKxZ9i/oX0zag+MF8= -github.com/go-openapi/swag v0.24.1/go.mod h1:sm8I3lCPlspsBBwUm1t5oZeWZS0s7m/A+Psg0ooRU0A= -github.com/go-openapi/swag/cmdutils v0.24.0 h1:KlRCffHwXFI6E5MV9n8o8zBRElpY4uK4yWyAMWETo9I= -github.com/go-openapi/swag/cmdutils v0.24.0/go.mod h1:uxib2FAeQMByyHomTlsP8h1TtPd54Msu2ZDU/H5Vuf8= -github.com/go-openapi/swag/conv v0.24.0 h1:ejB9+7yogkWly6pnruRX45D1/6J+ZxRu92YFivx54ik= -github.com/go-openapi/swag/conv v0.24.0/go.mod h1:jbn140mZd7EW2g8a8Y5bwm8/Wy1slLySQQ0ND6DPc2c= -github.com/go-openapi/swag/fileutils v0.24.0 h1:U9pCpqp4RUytnD689Ek/N1d2N/a//XCeqoH508H5oak= -github.com/go-openapi/swag/fileutils v0.24.0/go.mod h1:3SCrCSBHyP1/N+3oErQ1gP+OX1GV2QYFSnrTbzwli90= -github.com/go-openapi/swag/jsonname v0.24.0 h1:2wKS9bgRV/xB8c62Qg16w4AUiIrqqiniJFtZGi3dg5k= -github.com/go-openapi/swag/jsonname v0.24.0/go.mod h1:GXqrPzGJe611P7LG4QB9JKPtUZ7flE4DOVechNaDd7Q= -github.com/go-openapi/swag/jsonutils v0.24.0 h1:F1vE1q4pg1xtO3HTyJYRmEuJ4jmIp2iZ30bzW5XgZts= -github.com/go-openapi/swag/jsonutils v0.24.0/go.mod h1:vBowZtF5Z4DDApIoxcIVfR8v0l9oq5PpYRUuteVu6f0= -github.com/go-openapi/swag/loading v0.24.0 h1:ln/fWTwJp2Zkj5DdaX4JPiddFC5CHQpvaBKycOlceYc= -github.com/go-openapi/swag/loading v0.24.0/go.mod h1:gShCN4woKZYIxPxbfbyHgjXAhO61m88tmjy0lp/LkJk= -github.com/go-openapi/swag/mangling v0.24.0 h1:PGOQpViCOUroIeak/Uj/sjGAq9LADS3mOyjznmHy2pk= -github.com/go-openapi/swag/mangling v0.24.0/go.mod h1:Jm5Go9LHkycsz0wfoaBDkdc4CkpuSnIEf62brzyCbhc= -github.com/go-openapi/swag/netutils v0.24.0 h1:Bz02HRjYv8046Ycg/w80q3g9QCWeIqTvlyOjQPDjD8w= -github.com/go-openapi/swag/netutils v0.24.0/go.mod h1:WRgiHcYTnx+IqfMCtu0hy9oOaPR0HnPbmArSRN1SkZM= -github.com/go-openapi/swag/stringutils v0.24.0 h1:i4Z/Jawf9EvXOLUbT97O0HbPUja18VdBxeadyAqS1FM= -github.com/go-openapi/swag/stringutils v0.24.0/go.mod h1:5nUXB4xA0kw2df5PRipZDslPJgJut+NjL7D25zPZ/4w= -github.com/go-openapi/swag/typeutils v0.24.0 h1:d3szEGzGDf4L2y1gYOSSLeK6h46F+zibnEas2Jm/wIw= -github.com/go-openapi/swag/typeutils v0.24.0/go.mod h1:q8C3Kmk/vh2VhpCLaoR2MVWOGP8y7Jc8l82qCTd1DYI= -github.com/go-openapi/swag/yamlutils v0.24.0 h1:bhw4894A7Iw6ne+639hsBNRHg9iZg/ISrOVr+sJGp4c= -github.com/go-openapi/swag/yamlutils v0.24.0/go.mod h1:DpKv5aYuaGm/sULePoeiG8uwMpZSfReo1HR3Ik0yaG8= -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.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I= +github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w= +github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= +github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= +github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= +github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= +github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM= +github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc= +github.com/go-openapi/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw= +github.com/go-openapi/swag v0.28.0/go.mod h1:4qYnT3Cqr1p1VknOdPo70evN4rgQnAg6jwApHyxSGIg= +github.com/go-openapi/swag/cmdutils v0.28.0 h1:7TOeNtkYru1SG8Y34tDh9WBbLsMqGnptuxWiHREPZ4Q= +github.com/go-openapi/swag/cmdutils v0.28.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.28.0 h1:GtqqbyFe7vR5Y7ehxG9W6/OvrSFdf1OLeTGp40TqxH8= +github.com/go-openapi/swag/conv v0.28.0/go.mod h1:mbUE+mzctnhxi864m0Q07SpN8OowD9JhxmxuYvZZD/k= +github.com/go-openapi/swag/fileutils v0.28.0 h1:Z04XWQD7R8Eq+7GnOrjovBxPPmZzsS4gt2H2GPGIViU= +github.com/go-openapi/swag/fileutils v0.28.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8= +github.com/go-openapi/swag/jsonutils v0.28.0 h1:YIch6FwO7RXzeAnbO8Tu7dWBZeUEH+4nA0HXltVTnv4= +github.com/go-openapi/swag/jsonutils v0.28.0/go.mod h1:CYM3WlTUcagR2ZoHdz54di/cbBqt82tuxuXgAjxw+mg= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0 h1:qV+VVUAx5Oro8WjVWpZeql7YReTKhT4smR4zhcOQZr0= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= +github.com/go-openapi/swag/loading v0.28.0 h1:td8QZdZC9MIYGGSnSPKShKiK22I2tU5UQvuUhIBPRLU= +github.com/go-openapi/swag/loading v0.28.0/go.mod h1:rXB0QiQX5mMveXEA7ouM4KiiM9jVJe4K6BVbwhD1M4k= +github.com/go-openapi/swag/mangling v0.28.0 h1:pH8eyeNO9SLYsTMWJrurnNfKmDa28XrlA+HePVD53VM= +github.com/go-openapi/swag/mangling v0.28.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w= +github.com/go-openapi/swag/netutils v0.28.0 h1:YXN6TALEi2pzts8/8GNm6T61HTAZsieukGZidap989k= +github.com/go-openapi/swag/netutils v0.28.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ= +github.com/go-openapi/swag/pools v0.28.0 h1:HPMZWSAfce3rdVTFcjFiCIBtDg9h4x2QlRrHipwhxeU= +github.com/go-openapi/swag/pools v0.28.0/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE= +github.com/go-openapi/swag/stringutils v0.28.0 h1:ixsc9iYgDPubHL/8nSkbnryEHpD2VRlBMLKpQyPXcDU= +github.com/go-openapi/swag/stringutils v0.28.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM= +github.com/go-openapi/swag/typeutils v0.28.0 h1:nRBKSBXjDgf01VDPB3fWeD9nQuhCOVeIYAkUx2tbkyY= +github.com/go-openapi/swag/typeutils v0.28.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= +github.com/go-openapi/swag/yamlutils v0.28.0 h1:TV3JXH6DS46KUroDtMLAYHGkdWf5VDq3wVWFirmzROY= +github.com/go-openapi/swag/yamlutils v0.28.0/go.mod h1:x0q/yndZHEgk9Rx3DyDqzFUmHy55KTvIZldvF2dTJXs= +github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0= +github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo= +github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= +github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -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/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -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.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-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -156,10 +157,14 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y 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.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.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 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.30.0 h1:ll54AkzKunWkBn9wSoiUXbFZXYZTkdJGNXTBXUoolGo= +github.com/google/cel-go v0.30.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8= 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= @@ -175,24 +180,20 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -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-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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -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.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -201,8 +202,10 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -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.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/connect-compress/v2 v2.1.1 h1:ycZNp4rWOZBodVE2Ls5AzK4aHkyK+GteEfzRZgKNs+c= +github.com/klauspost/connect-compress/v2 v2.1.1/go.mod h1:9oilsPHJMzGKkjafSBk9J7iVo4mO+dw0G0KSdVpnlVE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -212,38 +215,24 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs= -github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= -github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= -github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= -github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k= -github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= -github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= -github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= -github.com/lestrrat-go/jwx/v2 v2.1.5 h1:PQI5gzadLfJ22ckLrejPVX6eGXKM4M4eGi5fW2jjA3o= -github.com/lestrrat-go/jwx/v2 v2.1.5/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU= -github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= -github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -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/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.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -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-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/metal-stack/metal-go v0.42.5 h1:G7r+FPOCe9NwhYAUs7zKUELjCIAd7jmati+AHHT/4Pc= -github.com/metal-stack/metal-go v0.42.5/go.mod h1:GSfXrAj55LGsUSMHWGDsmq5n056NG0yb1JM8bgfvKOw= -github.com/metal-stack/metal-lib v0.23.5 h1:ozrkB3DNr3Cqn8nkBvmzc/KKpYqC1j1mv2OVOj8i7Ac= -github.com/metal-stack/metal-lib v0.23.5/go.mod h1:7uyHIrE19dkLwCZyeh2jmd7IEq5pEpzrzUGLoMN1eqY= -github.com/metal-stack/security v0.9.4 h1:qgB4Yx48Wgi57a/ePWE1gdUn4RjilVySQAFRVIoPKBU= -github.com/metal-stack/security v0.9.4/go.mod h1:Qya3sKnaZ+1VmayGcMGgCBsVhzBvWYYx9hcvinfXB1Q= +github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= +github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +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/metal-stack/api v0.4.4 h1:NwJKCFHnbmsU7DjHLtBmpdPuPniXc2wDabHjdpXk3qA= +github.com/metal-stack/api v0.4.4/go.mod h1:E7f2GkKNSr4vBxhQwWrr/Mjnf4ctPqCX2dpDtXBqkBk= +github.com/metal-stack/metal-lib v0.26.1 h1:wMrhENm/HPq0t7cjCkhzepGD6dyxmX/4IMsaJZea874= +github.com/metal-stack/metal-lib v0.26.1/go.mod h1:tnx4MM5oml10EMN6Nq6oFSbjOKB9B27WUZQUyZ4MywA= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= +github.com/minio/minlz v1.2.0 h1:6IOBuiHg04QxvbFfgFLT/9sMaO/UhL7S+ApW1mK8q5A= +github.com/minio/minlz v1.2.0/go.mod h1:Ls9H7nlkASeCcdl5thjVD5Eraj6z+zGa7xtq57jIKD4= 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= @@ -252,75 +241,78 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd 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/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= -github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= -github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= -github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ= -github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs= -github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE= -github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= -github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= -github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +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/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= +github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo= +github.com/olekukonko/errors v1.2.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.1.6 h1:lGVTHO+Qc4Qm+fce/2h2m5y9LvqaW+DCN7xW9hsU3uA= +github.com/olekukonko/ll v0.1.6/go.mod h1:NVUmjBb/aCtUpjKk75BhWrOlARz3dqsM+OtszpY4o88= +github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I= +github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= +github.com/onsi/ginkgo/v2 v2.32.0 h1:Hw7s2pVrQo/8Yz5N77qdnpHaoc+c6cC9WIV1Jce+J6E= +github.com/onsi/ginkgo/v2 v2.32.0/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= +github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I= +github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pborman/uuid v0.0.0-20170612153648-e790cca94e6c/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= -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/pin/tftp v2.1.0+incompatible/go.mod h1:xVpZOMCXTy+A5QMjEVN0Glwa1sUvaJhFXbr/aAxuxGY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -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_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= +github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= 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.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= -github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= +github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= +github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= +github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= +github.com/rodaine/protogofakeit v0.1.1 h1:ZKouljuRM3A+TArppfBqnH8tGZHOwM/pjvtXe9DaXH8= +github.com/rodaine/protogofakeit v0.1.1/go.mod h1:pXn/AstBYMaSfc1/RqH3N82pBuxtWgejz1AlYpY1mI0= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= -github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= -github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sigma/bdoor v0.0.0-20160202064022-babf2a4017b0/go.mod h1:WBu7REWbxC/s/J06jsk//d+9DOz9BbsmcIrimuGRFbs= github.com/sigma/vmw-guestinfo v0.0.0-20160204083807-95dd4126d6e8/go.mod h1:JrRFFC0veyh0cibh0DAhriSY7/gV3kDdNaVUOmfx01U= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= -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/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.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.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +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.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= -github.com/spf13/viper v1.20.0/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +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/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.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= @@ -340,32 +332,21 @@ github.com/vmware/vmw-ovflib v0.0.0-20170608004843-1f217b9dc714/go.mod h1:jiPk45 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.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -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.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -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/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= -go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= -go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= -go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -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/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= -go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= 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.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/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/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/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= go4.org v0.0.0-20160314031811-03efcb870d84/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20201209231011-d4a079459e60/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= @@ -375,8 +356,6 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -385,6 +364,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20260718201538-764159d718ef h1:LkZ48HFgy/TvhTI0bcWkjgFkgLyKUwcTbDjS0DUjw+A= +golang.org/x/exp v0.0.0-20260718201538-764159d718ef/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -403,8 +384,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= +golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= +golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= 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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -423,15 +404,15 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -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.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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.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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -439,8 +420,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ 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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -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.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -459,14 +440,13 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.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= -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.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -474,12 +454,12 @@ 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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -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/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +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= @@ -506,8 +486,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE= +golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= 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= @@ -539,6 +519,10 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -546,8 +530,10 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -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/grpc v1.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ= +google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/integration/integration_test.go b/integration/integration_test.go index e586b04..853a7f1 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -4,12 +4,13 @@ import ( "fmt" "time" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v2 "github.com/metal-stack/firewall-controller-manager/api/v2" "github.com/metal-stack/firewall-controller-manager/api/v2/defaults" + "github.com/metal-stack/firewall-controller-manager/internal/test" "github.com/metal-stack/metal-lib/httperrors" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/stretchr/testify/mock" "sigs.k8s.io/controller-runtime/pkg/client" corev1 "k8s.io/api/core/v1" @@ -17,13 +18,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" testcommon "github.com/metal-stack/firewall-controller-manager/integration/common" - - metalfirewall "github.com/metal-stack/metal-go/api/client/firewall" - "github.com/metal-stack/metal-go/api/client/image" - "github.com/metal-stack/metal-go/api/client/machine" - "github.com/metal-stack/metal-go/api/client/network" - "github.com/metal-stack/metal-go/api/models" - metalclient "github.com/metal-stack/metal-go/test/client" ) var ( @@ -165,21 +159,11 @@ var _ = Context("integration test", Ordered, func() { Describe("the rolling update", Ordered, func() { When("creating a firewall deployment", Ordered, func() { It("the creation works", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{firewall1}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Create(ctx, deployment())).To(Succeed()) @@ -262,7 +246,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Created")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", *firewall1.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", firewall1.Allocation.Name))) }) It("should populate the machine status", func() { @@ -274,9 +258,9 @@ var _ = Context("integration test", Ordered, func() { return status }, 5*time.Second, interval).Should(Not(BeNil())) - Expect(status.MachineID).To(Equal(*firewall1.ID)) + Expect(status.MachineID).To(Equal(firewall1.Uuid)) Expect(status.CrashLoop).To(Equal(false)) - Expect(status.Liveliness).To(Equal("Alive")) + Expect(status.Liveliness).To(Equal("alive")) Expect(status.LastEvent).NotTo(BeNil()) Expect(status.LastEvent.Event).To(Equal("Phoned Home")) Expect(status.LastEvent.Message).To(Equal("phoning home")) @@ -290,7 +274,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Ready")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", *firewall1.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", firewall1.Allocation.Name))) }) It("should have the monitor condition true", func() { @@ -490,21 +474,11 @@ var _ = Context("integration test", Ordered, func() { Context("the spec is updated", func() { It("the update works", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: installingFirewall}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: installingFirewall}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{installingFirewall}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, installingFirewall) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) deploy := deployment() @@ -569,7 +543,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Created")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", *installingFirewall.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", installingFirewall.Allocation.Name))) }) It("should populate the machine status", func() { @@ -581,9 +555,9 @@ var _ = Context("integration test", Ordered, func() { return status }, 5*time.Second, interval).Should(Not(BeNil())) - Expect(status.MachineID).To(Equal(*installingFirewall.ID)) + Expect(status.MachineID).To(Equal(installingFirewall.Uuid)) Expect(status.CrashLoop).To(Equal(false)) - Expect(status.Liveliness).To(Equal("Alive")) + Expect(status.Liveliness).To(Equal("alive")) Expect(status.LastEvent).NotTo(BeNil()) Expect(status.LastEvent.Event).To(Equal("Installing")) Expect(status.LastEvent.Message).To(Equal("is installing")) @@ -597,7 +571,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("NotReady")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is not ready.", *installingFirewall.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is not ready.", installingFirewall.Allocation.Name))) }) It("should not yet have a distance configured", func() { @@ -648,14 +622,14 @@ var _ = Context("integration test", Ordered, func() { Expect(nws).To(BeComparableTo([]v2.FirewallNetwork{ { - ASN: installingFirewall.Allocation.Networks[0].Asn, - DestinationPrefixes: installingFirewall.Allocation.Networks[0].Destinationprefixes, + ASN: new(int64(installingFirewall.Allocation.Networks[0].Asn)), + DestinationPrefixes: installingFirewall.Allocation.Networks[0].DestinationPrefixes, IPs: installingFirewall.Allocation.Networks[0].Ips, - Nat: installingFirewall.Allocation.Networks[0].Nat, - NetworkID: installingFirewall.Allocation.Networks[0].Networkid, - NetworkType: installingFirewall.Allocation.Networks[0].Networktype, + Nat: new(installingFirewall.Allocation.Networks[0].NatType == apiv2.NATType_NAT_TYPE_IPV4_MASQUERADE), + NetworkID: new(installingFirewall.Allocation.Networks[0].Network), + NetworkType: new("child"), Prefixes: network1.Prefixes, - Vrf: installingFirewall.Allocation.Networks[0].Vrf, + Vrf: new(int64(installingFirewall.Allocation.Networks[0].Vrf)), }, })) }) @@ -792,21 +766,12 @@ var _ = Context("integration test", Ordered, func() { When("the firewall gets ready and the firewall-controller connects", Ordered, func() { It("should allow an update of the firewall monitor", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Machine: func(m *mock.Mock) { - m.On("FreeMachine", mock.Anything, nil).Return(&machine.FreeMachineOK{Payload: &models.V1MachineResponse{ID: firewall1.ID}}, nil).Maybe() - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Firewall: func(m *mock.Mock) { - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: readyFirewall}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{readyFirewall}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, readyFirewall) + mockMachineDelete(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(mon), mon)).To(Succeed()) // refetch @@ -841,14 +806,14 @@ var _ = Context("integration test", Ordered, func() { mon := testcommon.WaitForResourceAmount(k8sClient, ctx, namespaceName, 1, &v2.FirewallMonitorList{}, func(l *v2.FirewallMonitorList) []*v2.FirewallMonitor { return l.GetItems() }, 15*time.Second) - Expect(mon.MachineStatus.MachineID).To(Equal(*readyFirewall.ID)) + Expect(mon.MachineStatus.MachineID).To(Equal(readyFirewall.Uuid)) }) It("should delete the firewall", func() { fw = testcommon.WaitForResourceAmount(k8sClient, ctx, namespaceName, 1, &v2.FirewallList{}, func(l *v2.FirewallList) []*v2.Firewall { return l.GetItems() }, 15*time.Second) - Expect(fw.Status.MachineStatus.MachineID).To(Equal(*readyFirewall.ID)) + Expect(fw.Status.MachineStatus.MachineID).To(Equal(readyFirewall.Uuid)) }) It("should delete the firewall set", func() { @@ -882,22 +847,12 @@ var _ = Context("integration test", Ordered, func() { Describe("the deletion flow", Ordered, func() { When("deleting the firewall deployment", func() { It("the deletion finishes", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{firewall1}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("FreeMachine", mock.Anything, nil).Return(&machine.FreeMachineOK{Payload: &models.V1MachineResponse{ID: firewall1.ID}}, nil).Maybe() - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, firewall1) + mockMachineDelete(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Delete(ctx, deployment())).To(Succeed()) @@ -933,21 +888,11 @@ var _ = Context("integration test", Ordered, func() { Describe("the recreate update", Ordered, func() { When("creating a firewall deployment", Ordered, func() { It("the creation works", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{firewall1}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) deploy := deployment() @@ -1032,7 +977,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Created")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", *firewall1.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", firewall1.Allocation.Name))) }) It("should populate the machine status", func() { @@ -1044,9 +989,9 @@ var _ = Context("integration test", Ordered, func() { return status }, 5*time.Second, interval).Should(Not(BeNil())) - Expect(status.MachineID).To(Equal(*firewall1.ID)) + Expect(status.MachineID).To(Equal(firewall1.Uuid)) Expect(status.CrashLoop).To(Equal(false)) - Expect(status.Liveliness).To(Equal("Alive")) + Expect(status.Liveliness).To(Equal("alive")) Expect(status.LastEvent).NotTo(BeNil()) Expect(status.LastEvent.Event).To(Equal("Phoned Home")) Expect(status.LastEvent.Message).To(Equal("phoning home")) @@ -1060,7 +1005,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Ready")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", *firewall1.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", firewall1.Allocation.Name))) }) It("should have the provisioned condition true", func() { @@ -1257,21 +1202,12 @@ var _ = Context("integration test", Ordered, func() { Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment()), deploy)).To(Succeed()) - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: readyFirewall}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{readyFirewall}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("FreeMachine", mock.Anything, nil).Return(nil, &machine.FreeMachineDefault{Payload: httperrors.Conflict(fmt.Errorf("deletion blocked"))}).Maybe() - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, readyFirewall) + mockMachineDeleteErr(m, httperrors.Conflict(fmt.Errorf("deletion blocked"))) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) deploy.Spec.Template.Spec.Networks = []string{"internet", "mpls"} @@ -1295,22 +1231,12 @@ var _ = Context("integration test", Ordered, func() { Context("the old generation disappears", Ordered, func() { It("should delete the firewall set", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: readyFirewall}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: readyFirewall}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{readyFirewall}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("FreeMachine", mock.Anything, nil).Return(&machine.FreeMachineOK{Payload: &models.V1MachineResponse{ID: firewall1.ID}}, nil).Maybe() - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, readyFirewall) + mockMachineDelete(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Eventually(func() bool { @@ -1365,20 +1291,11 @@ var _ = Context("integration test", Ordered, func() { When("the firewall-controller connects", Ordered, func() { It("should allow an update of the firewall monitor", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Machine: func(m *mock.Mock) { - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Firewall: func(m *mock.Mock) { - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: readyFirewall}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{readyFirewall}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, readyFirewall) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(newMon), newMon)).To(Succeed()) // refetch @@ -1420,7 +1337,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Created")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", *readyFirewall.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", readyFirewall.Allocation.Name))) }) It("should populate the machine status", func() { @@ -1432,9 +1349,9 @@ var _ = Context("integration test", Ordered, func() { return status }, 5*time.Second, interval).Should(Not(BeNil())) - Expect(status.MachineID).To(Equal(*readyFirewall.ID)) + Expect(status.MachineID).To(Equal(readyFirewall.Uuid)) Expect(status.CrashLoop).To(Equal(false)) - Expect(status.Liveliness).To(Equal("Alive")) + Expect(status.Liveliness).To(Equal("alive")) Expect(status.LastEvent).NotTo(BeNil()) Expect(status.LastEvent.Event).To(Equal("Phoned Home")) Expect(status.LastEvent.Message).To(Equal("is phoning home")) @@ -1448,7 +1365,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Ready")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", *readyFirewall.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", readyFirewall.Allocation.Name))) }) It("should have the provisioned condition true", func() { @@ -1506,14 +1423,14 @@ var _ = Context("integration test", Ordered, func() { Expect(nws).To(BeComparableTo([]v2.FirewallNetwork{ { - ASN: readyFirewall.Allocation.Networks[0].Asn, - DestinationPrefixes: readyFirewall.Allocation.Networks[0].Destinationprefixes, + ASN: new(int64(readyFirewall.Allocation.Networks[0].Asn)), + DestinationPrefixes: readyFirewall.Allocation.Networks[0].DestinationPrefixes, IPs: readyFirewall.Allocation.Networks[0].Ips, - Nat: readyFirewall.Allocation.Networks[0].Nat, - NetworkID: readyFirewall.Allocation.Networks[0].Networkid, - NetworkType: readyFirewall.Allocation.Networks[0].Networktype, + Nat: new(readyFirewall.Allocation.Networks[0].NatType == apiv2.NATType_NAT_TYPE_IPV4_MASQUERADE), + NetworkID: new(readyFirewall.Allocation.Networks[0].Network), + NetworkType: new("child"), Prefixes: network1.Prefixes, - Vrf: readyFirewall.Allocation.Networks[0].Vrf, + Vrf: new(int64(readyFirewall.Allocation.Networks[0].Vrf)), }, })) }) @@ -1639,22 +1556,12 @@ var _ = Context("integration test", Ordered, func() { Describe("the deletion flow", Ordered, func() { When("deleting the firewall deployment", func() { It("the deletion finishes", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{firewall1}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("FreeMachine", mock.Anything, nil).Return(&machine.FreeMachineOK{Payload: &models.V1MachineResponse{ID: firewall1.ID}}, nil).Maybe() - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, firewall1) + mockMachineDelete(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Delete(ctx, deployment())).To(Succeed()) @@ -1746,20 +1653,11 @@ var _ = Context("integration test", Ordered, func() { When("creating a firewall resource (for an existing firewall)", Ordered, func() { It("the creation works", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{firewall1}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Create(ctx, fw)).To(Succeed()) @@ -1828,7 +1726,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Created")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", *firewall1.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q created successfully.", firewall1.Allocation.Name))) }) It("should populate the machine status", func() { @@ -1840,9 +1738,9 @@ var _ = Context("integration test", Ordered, func() { return status }, 5*time.Second, interval).Should(Not(BeNil())) - Expect(status.MachineID).To(Equal(*firewall1.ID)) + Expect(status.MachineID).To(Equal(firewall1.Uuid)) Expect(status.CrashLoop).To(Equal(false)) - Expect(status.Liveliness).To(Equal("Alive")) + Expect(status.Liveliness).To(Equal("alive")) Expect(status.LastEvent).NotTo(BeNil()) Expect(status.LastEvent.Event).To(Equal("Phoned Home")) Expect(status.LastEvent.Message).To(Equal("phoning home")) @@ -1856,7 +1754,7 @@ var _ = Context("integration test", Ordered, func() { Expect(cond.LastTransitionTime).NotTo(BeZero()) Expect(cond.LastUpdateTime).NotTo(BeZero()) Expect(cond.Reason).To(Equal("Ready")) - Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", *firewall1.Allocation.Name))) + Expect(cond.Message).To(Equal(fmt.Sprintf("Firewall %q is phoning home and alive.", firewall1.Allocation.Name))) }) It("should have the provisioned condition true", func() { @@ -1974,22 +1872,12 @@ var _ = Context("integration test", Ordered, func() { Describe("the deletion flow", Ordered, func() { When("deleting the firewall deployment", func() { It("the deletion finishes", func() { - swapMetalClient(&metalclient.MetalMockFns{ - Firewall: func(m *mock.Mock) { - m.On("AllocateFirewall", mock.Anything, nil).Return(&metalfirewall.AllocateFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewall", mock.Anything, nil).Return(&metalfirewall.FindFirewallOK{Payload: firewall1}, nil).Maybe() - m.On("FindFirewalls", mock.Anything, nil).Return(&metalfirewall.FindFirewallsOK{Payload: []*models.V1FirewallResponse{firewall1}}, nil).Maybe() - }, - Network: func(m *mock.Mock) { - m.On("FindNetwork", mock.Anything, nil).Return(&network.FindNetworkOK{Payload: network1}, nil).Maybe() - }, - Machine: func(m *mock.Mock) { - m.On("FreeMachine", mock.Anything, nil).Return(&machine.FreeMachineOK{Payload: &models.V1MachineResponse{ID: firewall1.ID}}, nil).Maybe() - m.On("UpdateMachine", mock.Anything, nil).Return(&machine.UpdateMachineOK{Payload: &models.V1MachineResponse{}}, nil).Maybe() - }, - Image: func(m *mock.Mock) { - m.On("FindLatestImage", mock.Anything, nil).Return(&image.FindLatestImageOK{Payload: image1}, nil).Maybe() - }, + swapMetalClient(func(m *test.Client) { + mockMachine(m, firewall1) + mockMachineDelete(m, firewall1) + mockMachineUpdate(m) + mockNetwork(m, network1) + mockImage(m, image1) }) Expect(k8sClient.Delete(ctx, deployment())).To(Succeed()) diff --git a/integration/metal_resources_test.go b/integration/metal_resources_test.go index a8c9605..9a75c12 100644 --- a/integration/metal_resources_test.go +++ b/integration/metal_resources_test.go @@ -1,327 +1,335 @@ package controllers_test import ( + "context" "time" - "github.com/go-openapi/strfmt" - metalgo "github.com/metal-stack/metal-go" - "github.com/metal-stack/metal-go/api/models" - metalclient "github.com/metal-stack/metal-go/test/client" - "github.com/metal-stack/metal-lib/pkg/net" - "github.com/metal-stack/metal-lib/pkg/pointer" + apiv2client "github.com/metal-stack/api/go/client" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/firewall-controller-manager/internal/test" + "google.golang.org/protobuf/types/known/timestamppb" ) var ( - metalClient metalgo.Client + metalClient apiv2client.Client + metalMock *test.Client testTime = time.Now() - firewall1 = &models.V1FirewallResponse{ - Allocation: &models.V1MachineAllocation{ - BootInfo: &models.V1BootInfo{ - Bootloaderid: new("bootloaderid"), - Cmdline: new("cmdline"), - ImageID: new("imageid"), - Initrd: new("initrd"), - Kernel: new("kernel"), - OsPartition: new("ospartition"), - PrimaryDisk: new("primarydisk"), + firewall1 = &apiv2.Machine{ + Allocation: &apiv2.MachineAllocation{ + Meta: &apiv2.Meta{ + CreatedAt: timestamppb.New(testTime.Add(-14 * 24 * time.Hour)), }, - Created: new(strfmt.DateTime(testTime.Add(-14 * 24 * time.Hour))), - Creator: new("creator"), + CreatedBy: "creator", Description: "firewall allocation 1", - Filesystemlayout: fsl1, - Hostname: new("firewall-hostname-1"), + FilesystemLayout: fsl1, + Hostname: "firewall-hostname-1", Image: image1, - Name: new("firewall-1"), - Networks: []*models.V1MachineNetwork{ + Name: "firewall-1", + Networks: []*apiv2.MachineNetwork{ { - Asn: new(int64(200)), - Destinationprefixes: []string{"2.2.2.2"}, + Asn: uint32(200), + DestinationPrefixes: []string{"2.2.2.2"}, Ips: []string{"1.1.1.1"}, - Nat: new(false), - Networkid: new("private"), - Networktype: pointer.Pointer(net.PrivatePrimaryUnshared), + NatType: apiv2.NATType_NAT_TYPE_NONE, + Network: "private", + NetworkType: apiv2.NetworkType_NETWORK_TYPE_CHILD, Prefixes: []string{"prefixes"}, - Private: new(true), - Underlay: new(false), - Vrf: new(int64(100)), + Vrf: uint64(100), }, }, - Project: new("project-1"), - Reinstall: new(false), - Role: pointer.Pointer(models.V1MachineAllocationRoleFirewall), - SSHPubKeys: []string{"sshpubkey"}, - Succeeded: new(true), - UserData: "---userdata---", + Project: "project-1", + AllocationType: apiv2.MachineAllocationType_MACHINE_ALLOCATION_TYPE_FIREWALL, + SshPublicKeys: []string{"sshpubkey"}, + Userdata: "---userdata---", }, - Bios: &models.V1MachineBIOS{ - Date: new("biosdata"), - Vendor: new("biosvendor"), - Version: new("biosversion"), - }, - Description: "firewall 1", - Events: &models.V1MachineRecentProvisioningEvents{ - CrashLoop: new(false), - FailedMachineReclaim: new(false), - LastErrorEvent: &models.V1MachineProvisioningEvent{ - Event: new("Crashed"), - Message: "crash", - Time: strfmt.DateTime(testTime.Add(-10 * 24 * time.Hour)), - }, - LastEventTime: strfmt.DateTime(testTime.Add(-7 * 24 * time.Hour)), - Log: []*models.V1MachineProvisioningEvent{ + RecentProvisioningEvents: &apiv2.MachineRecentProvisioningEvents{ + Events: []*apiv2.MachineProvisioningEvent{ { - Event: new("Phoned Home"), + Time: timestamppb.New(testTime.Add(-7 * 24 * time.Hour)), + Event: apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_PHONED_HOME, Message: "phoning home", - Time: strfmt.DateTime(testTime.Add(-7 * 24 * time.Hour)), }, }, + LastErrorEvent: &apiv2.MachineProvisioningEvent{ + Time: timestamppb.New(testTime.Add(-10 * 24 * time.Hour)), + Event: apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_CRASHED, + Message: "crash", + }, + LastEventTime: timestamppb.New(testTime.Add(-7 * 24 * time.Hour)), + State: apiv2.MachineProvisioningEventState_MACHINE_PROVISIONING_EVENT_STATE_UNSPECIFIED, }, - Hardware: &models.V1MachineHardware{ - CPUCores: new(int32(16)), - Disks: []*models.V1MachineBlockDevice{}, - Memory: new(int64(32)), - Nics: []*models.V1MachineNic{}, - }, - ID: new("1"), - Ledstate: &models.V1ChassisIdentifyLEDState{ - Description: new(""), - Value: new(""), + Hardware: &apiv2.MachineHardware{ + Cpus: []*apiv2.MetalCPU{ + { + Cores: 16, + }, + }, + Disks: []*apiv2.MachineBlockDevice{}, + Memory: uint64(32), + Nics: []*apiv2.MachineNic{}, }, - Liveliness: new("Alive"), - Name: "firewall-1", - Partition: partition1, - Rackid: "rack-1", - Size: size1, - State: &models.V1MachineState{ - Description: new("state"), - Issuer: "issuer", - MetalHammerVersion: new("version"), - Value: new(""), + Uuid: "1", + Status: &apiv2.MachineStatus{ + Condition: &apiv2.MachineCondition{ + Description: "state", + Issuer: "issuer", + }, + LedState: &apiv2.MachineChassisIdentifyLEDState{}, + Liveliness: apiv2.MachineLiveliness_MACHINE_LIVELINESS_ALIVE, + MetalHammerVersion: "version", }, - Tags: []string{"a"}, + Partition: partition1, + Rack: "rack-1", + Size: size1, } - firewall2 = func(event, message string) *models.V1FirewallResponse { - return &models.V1FirewallResponse{ - Allocation: &models.V1MachineAllocation{ - BootInfo: &models.V1BootInfo{ - Bootloaderid: new("bootloaderid"), - Cmdline: new("cmdline"), - ImageID: new("imageid"), - Initrd: new("initrd"), - Kernel: new("kernel"), - OsPartition: new("ospartition"), - PrimaryDisk: new("primarydisk"), + firewall2 = func(event, message string) *apiv2.Machine { + return &apiv2.Machine{ + Allocation: &apiv2.MachineAllocation{ + Meta: &apiv2.Meta{ + CreatedAt: timestamppb.New(testTime), }, - Created: new(strfmt.DateTime(testTime)), - Creator: new("creator"), + CreatedBy: "creator", Description: "firewall allocation 2", - Filesystemlayout: fsl1, - Hostname: new("firewall-hostname-2"), + FilesystemLayout: fsl1, + Hostname: "firewall-hostname-2", Image: image1, - Name: new("firewall-2"), - Networks: []*models.V1MachineNetwork{ + Name: "firewall-2", + Networks: []*apiv2.MachineNetwork{ { - Asn: new(int64(200)), - Destinationprefixes: []string{"2.2.2.2"}, + Asn: uint32(200), + DestinationPrefixes: []string{"2.2.2.2"}, Ips: []string{"1.1.1.1"}, - Nat: new(false), - Networkid: new("private"), - Networktype: pointer.Pointer(net.PrivatePrimaryUnshared), + NatType: apiv2.NATType_NAT_TYPE_NONE, + Network: "private", + NetworkType: apiv2.NetworkType_NETWORK_TYPE_CHILD, Prefixes: []string{"prefixes"}, - Private: new(true), - Underlay: new(false), - Vrf: new(int64(100)), + Vrf: uint64(100), }, }, - Project: new("project-1"), - Reinstall: new(false), - Role: pointer.Pointer(models.V1MachineAllocationRoleFirewall), - SSHPubKeys: []string{"sshpubkey"}, - Succeeded: new(true), - UserData: "---userdata---", + Project: "project-1", + AllocationType: apiv2.MachineAllocationType_MACHINE_ALLOCATION_TYPE_FIREWALL, + SshPublicKeys: []string{"sshpubkey"}, + Userdata: "---userdata---", }, - Bios: &models.V1MachineBIOS{ - Date: new("biosdata"), - Vendor: new("biosvendor"), - Version: new("biosversion"), - }, - Description: "firewall 2", - Events: &models.V1MachineRecentProvisioningEvents{ - CrashLoop: new(false), - FailedMachineReclaim: new(false), - LastErrorEvent: &models.V1MachineProvisioningEvent{}, - LastEventTime: strfmt.DateTime(testTime.Add(-1 * time.Minute)), - Log: []*models.V1MachineProvisioningEvent{ + RecentProvisioningEvents: &apiv2.MachineRecentProvisioningEvents{ + Events: []*apiv2.MachineProvisioningEvent{ { - Event: new(event), + Time: timestamppb.New(testTime.Add(-7 * 24 * time.Hour)), + Event: provisioningEventType(event), Message: message, - Time: strfmt.DateTime(testTime.Add(-7 * 24 * time.Hour)), }, }, + LastErrorEvent: &apiv2.MachineProvisioningEvent{}, + LastEventTime: timestamppb.New(testTime.Add(-1 * time.Minute)), + State: apiv2.MachineProvisioningEventState_MACHINE_PROVISIONING_EVENT_STATE_UNSPECIFIED, }, - Hardware: &models.V1MachineHardware{ - CPUCores: new(int32(16)), - Disks: []*models.V1MachineBlockDevice{}, - Memory: new(int64(32)), - Nics: []*models.V1MachineNic{}, - }, - ID: new("2"), - Ledstate: &models.V1ChassisIdentifyLEDState{ - Description: new(""), - Value: new(""), + Hardware: &apiv2.MachineHardware{ + Cpus: []*apiv2.MetalCPU{ + { + Cores: 16, + }, + }, + Disks: []*apiv2.MachineBlockDevice{}, + Memory: uint64(32), + Nics: []*apiv2.MachineNic{}, }, - Liveliness: new("Alive"), - Name: "firewall-2", - Partition: partition1, - Rackid: "rack-1", - Size: size1, - State: &models.V1MachineState{ - Description: new("state"), - Issuer: "issuer", - MetalHammerVersion: new("version"), - Value: new(""), + Uuid: "2", + Status: &apiv2.MachineStatus{ + Condition: &apiv2.MachineCondition{ + Description: "state", + Issuer: "issuer", + }, + LedState: &apiv2.MachineChassisIdentifyLEDState{}, + Liveliness: apiv2.MachineLiveliness_MACHINE_LIVELINESS_ALIVE, + MetalHammerVersion: "version", }, - Tags: []string{"b"}, + Partition: partition1, + Rack: "rack-1", + Size: size1, } } - fsl1 = &models.V1FilesystemLayoutResponse{ - Constraints: &models.V1FilesystemLayoutConstraints{ + fsl1 = &apiv2.FilesystemLayout{ + Constraints: &apiv2.FilesystemLayoutConstraints{ Images: map[string]string{ "os-image": "*", }, Sizes: []string{"size1"}, }, - Description: "fsl 1", - Disks: []*models.V1Disk{ + Description: new("fsl 1"), + Disks: []*apiv2.Disk{ { - Device: new("/dev/sda"), - Partitions: []*models.V1DiskPartition{ + Device: "/dev/sda", + Partitions: []*apiv2.DiskPartition{ { - Gpttype: new("ef00"), - Label: "efi", - Number: new(int64(1)), - Size: new(int64(1000)), + GptType: apiv2.GPTType_GPT_TYPE_BOOT.Enum(), + Label: new("efi"), + Number: uint32(1), + Size: uint64(1000), }, }, - Wipeonreinstall: new(true), }, }, - Filesystems: []*models.V1Filesystem{ + Filesystems: []*apiv2.Filesystem{ { - Createoptions: []string{"-F 32"}, - Device: new("/dev/sda1"), - Format: new("vfat"), - Label: "efi", - Mountoptions: []string{"noexec"}, - Path: "/boot/efi", + CreateOptions: []string{"-F 32"}, + Device: "/dev/sda1", + Format: apiv2.Format_FORMAT_VFAT, + Label: new("efi"), + MountOptions: []string{"noexec"}, + Path: new("/boot/efi"), }, { - Createoptions: []string{}, - Device: new("tmpfs"), - Format: new("tmpfs"), - Label: "", - Mountoptions: []string{"noexec"}, - Path: "/tmp", + CreateOptions: []string{}, + Device: "tmpfs", + Format: apiv2.Format_FORMAT_TMPFS, + Label: new(""), + MountOptions: []string{"noexec"}, + Path: new("/tmp"), }, }, - ID: new("1"), - Logicalvolumes: []*models.V1LogicalVolume{ + Id: "1", + LogicalVolumes: []*apiv2.LogicalVolume{ { - Lvmtype: new("linear"), - Name: new("varlib"), - Size: new(int64(5000)), - Volumegroup: new("lvm"), + LvmType: apiv2.LVMType_LVM_TYPE_LINEAR, + Name: "varlib", + Size: uint64(5000), + VolumeGroup: "lvm", }, }, - Name: "fsl1", - Raid: []*models.V1Raid{}, - Volumegroups: []*models.V1VolumeGroup{ + Name: new("fsl1"), + Raid: []*apiv2.Raid{}, + VolumeGroups: []*apiv2.VolumeGroup{ { Devices: []string{"/dev/nvme0n1"}, - Name: new("lvm"), + Name: "lvm", Tags: []string{}, }, }, } - imageExpiration = new(strfmt.DateTime(testTime.Add(3 * 24 * time.Hour))) - image1 = &models.V1ImageResponse{ - Classification: "supported", - Description: "firewall-image-description", - ExpirationDate: imageExpiration, - Features: []string{"firewall"}, - ID: new("firewall-ubuntu-2.0"), - Name: "firewall-image-name", - URL: "firewall-image-url", + imageExpiration = timestamppb.New(testTime.Add(3 * 24 * time.Hour)) + image1 = &apiv2.Image{ + Classification: apiv2.ImageClassification_IMAGE_CLASSIFICATION_SUPPORTED, + Description: new("firewall-image-description"), + ExpiresAt: imageExpiration, + Features: []apiv2.ImageFeature{apiv2.ImageFeature_IMAGE_FEATURE_FIREWALL}, + Id: "firewall-ubuntu-2.0", + Name: new("firewall-image-name"), + Url: "firewall-image-url", } - partition1 = &models.V1PartitionResponse{ - Bootconfig: &models.V1PartitionBootConfiguration{ + partition1 = &apiv2.Partition{ + BootConfiguration: &apiv2.PartitionBootConfiguration{ Commandline: "commandline", - Imageurl: "imageurl", - Kernelurl: "kernelurl", + ImageUrl: "imageurl", + KernelUrl: "kernelurl", }, - Description: "partition 1", - ID: new("1"), - Mgmtserviceaddress: "mgmt", - Name: "partition-1", + Description: "partition 1", + Id: "1", + MgmtServiceAddresses: []string{"mgmt"}, } - size1 = &models.V1SizeResponse{ - Constraints: []*models.V1SizeConstraint{ + size1 = &apiv2.Size{ + Constraints: []*apiv2.SizeConstraint{ { - Max: int64(2), - Min: int64(1), - Type: new("storage"), + Max: uint64(2), + Min: uint64(1), + Type: apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_STORAGE, }, { - Max: int64(4), - Min: int64(3), - Type: new("memory"), + Max: uint64(4), + Min: uint64(3), + Type: apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_MEMORY, }, { - Max: int64(6), - Min: int64(5), - Type: new("cores"), + Max: uint64(6), + Min: uint64(5), + Type: apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_CORES, }, }, - Description: "size 1", - ID: new("1"), - Name: "size-1", + Description: new("size 1"), + Id: "1", + Name: new("size-1"), } - network1 = &models.V1NetworkResponse{ - Description: "network 1", - Destinationprefixes: []string{"dest"}, - ID: new("nw1"), - Labels: map[string]string{"a": "b"}, - Name: "network-1", - Nat: new(true), - Parentnetworkid: "", - Partitionid: "partition-1", + network1 = &apiv2.Network{ + Description: new("network 1"), + DestinationPrefixes: []string{"dest"}, + Id: "nw1", + Name: new("network-1"), + NatType: apiv2.NATType_NAT_TYPE_IPV4_MASQUERADE, + Partition: new("partition-1"), Prefixes: []string{"prefix"}, - Privatesuper: new(true), - Projectid: "", - Shared: false, - Underlay: new(true), - Usage: &models.V1NetworkUsage{ - AvailableIps: new(int64(100)), - AvailablePrefixes: new(int64(200)), - UsedIps: new(int64(300)), - UsedPrefixes: new(int64(400)), - }, - Vrf: 50, - Vrfshared: true, + Project: new(""), + Type: apiv2.NetworkType_NETWORK_TYPE_UNDERLAY, + Vrf: new(uint32(50)), } ) -// we are sharing a client for the tests, so we need to make sure we do not run contradicting tests in parallel -// we can swap the client with this function -func swapMetalClient(mockFns *metalclient.MetalMockFns) { - newClient, _ := metalclient.NewMetalMockClient(testingT, mockFns) +func provisioningEventType(event string) apiv2.MachineProvisioningEventType { + switch event { + case "Phoned Home": + return apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_PHONED_HOME + case "Installing": + return apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_INSTALLING + case "Crashed": + return apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_CRASHED + default: + return apiv2.MachineProvisioningEventType_MACHINE_PROVISIONING_EVENT_TYPE_UNSPECIFIED + } +} - if metalClient == nil { - metalClient = newClient - return +// we are sharing a metal client for the tests, so we need to make sure we do not run contradicting tests in parallel +// the shared metal mock client is reconfigured with this function +func swapMetalClient(fns func(*test.Client)) { + if metalMock != nil && fns != nil { + fns(metalMock) } +} - metalMockClient := metalClient.(*metalclient.MetalMockClient) - *metalMockClient = *newClient // nolint for testing this is just fine +// mockMachine configures the machine service handlers to return the given firewalls. +func mockMachine(m *test.Client, fws ...*apiv2.Machine) { + machine := fws[0] + + m.OnMachineGet = func(_ context.Context, _ *apiv2.MachineServiceGetRequest) (*apiv2.MachineServiceGetResponse, error) { + return &apiv2.MachineServiceGetResponse{Machine: machine}, nil + } + m.OnMachineCreate = func(_ context.Context, _ *apiv2.MachineServiceCreateRequest) (*apiv2.MachineServiceCreateResponse, error) { + return &apiv2.MachineServiceCreateResponse{Machine: machine}, nil + } + m.OnMachineList = func(_ context.Context, _ *apiv2.MachineServiceListRequest) (*apiv2.MachineServiceListResponse, error) { + return &apiv2.MachineServiceListResponse{Machines: fws}, nil + } +} + +// mockMachineDelete configures the machine delete handler to return the given firewall. +func mockMachineDelete(m *test.Client, machine *apiv2.Machine) { + m.OnMachineDelete = func(_ context.Context, _ *apiv2.MachineServiceDeleteRequest) (*apiv2.MachineServiceDeleteResponse, error) { + return &apiv2.MachineServiceDeleteResponse{Machine: machine}, nil + } +} + +// mockMachineDeleteErr configures the machine delete handler to return the given error. +func mockMachineDeleteErr(m *test.Client, err error) { + m.OnMachineDelete = func(_ context.Context, _ *apiv2.MachineServiceDeleteRequest) (*apiv2.MachineServiceDeleteResponse, error) { + return nil, err + } +} + +// mockMachineUpdate configures the machine update handler to succeed. +func mockMachineUpdate(m *test.Client) { + m.OnMachineUpdate = func(_ context.Context, _ *apiv2.MachineServiceUpdateRequest) (*apiv2.MachineServiceUpdateResponse, error) { + return &apiv2.MachineServiceUpdateResponse{Machine: &apiv2.Machine{}}, nil + } +} + +// mockNetwork configures the network service handler to return the given network. +func mockNetwork(m *test.Client, nw *apiv2.Network) { + m.OnNetworkGet = func(_ context.Context, _ *apiv2.NetworkServiceGetRequest) (*apiv2.NetworkServiceGetResponse, error) { + return &apiv2.NetworkServiceGetResponse{Network: nw}, nil + } +} + +// mockImage configures the image service handler to return the given image. +func mockImage(m *test.Client, img *apiv2.Image) { + m.OnImageLatest = func(_ context.Context, _ *apiv2.ImageServiceLatestRequest) (*apiv2.ImageServiceLatestResponse, error) { + return &apiv2.ImageServiceLatestResponse{Image: img}, nil + } } diff --git a/integration/suite_test.go b/integration/suite_test.go index 8db2fed..b31e717 100644 --- a/integration/suite_test.go +++ b/integration/suite_test.go @@ -18,7 +18,7 @@ import ( "github.com/metal-stack/firewall-controller-manager/controllers/set" "github.com/metal-stack/firewall-controller-manager/controllers/timeout" "github.com/metal-stack/firewall-controller-manager/controllers/update" - metalclient "github.com/metal-stack/metal-go/test/client" + "github.com/metal-stack/firewall-controller-manager/internal/test" "github.com/metal-stack/metal-lib/pkg/tag" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -110,7 +110,8 @@ var _ = BeforeSuite(func() { }) Expect(err).ToNot(HaveOccurred()) - metalClient, _ = metalclient.NewMetalMockClient(testingT, nil) + metalMock = test.New(testingT) + metalClient = metalMock.Client() cc, err := controllerconfig.New(&controllerconfig.NewControllerConfig{ SeedClient: k8sClient, diff --git a/internal/test/mock.go b/internal/test/mock.go new file mode 100644 index 0000000..810d1e3 --- /dev/null +++ b/internal/test/mock.go @@ -0,0 +1,182 @@ +// Package metalmock provides a configurable mock for the metal-stack apiv2 connect +// client (github.com/metal-stack/api) that can be injected into the controllers via +// the ControllerConfig. It uses a connect client interceptor to serve the machine, +// network and image service calls and delegates each call to a programmable handler. +package test + +import ( + "context" + "sync" + "testing" + + "connectrpc.com/connect" + apiv2client "github.com/metal-stack/api/go/client" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/api/go/metalstack/api/v2/apiv2connect" +) + +// Handler signatures for the service methods used by the controllers. + +type ( + MachineGetFn func(context.Context, *apiv2.MachineServiceGetRequest) (*apiv2.MachineServiceGetResponse, error) + MachineCreateFn func(context.Context, *apiv2.MachineServiceCreateRequest) (*apiv2.MachineServiceCreateResponse, error) + MachineUpdateFn func(context.Context, *apiv2.MachineServiceUpdateRequest) (*apiv2.MachineServiceUpdateResponse, error) + MachineListFn func(context.Context, *apiv2.MachineServiceListRequest) (*apiv2.MachineServiceListResponse, error) + MachineDeleteFn func(context.Context, *apiv2.MachineServiceDeleteRequest) (*apiv2.MachineServiceDeleteResponse, error) + + NetworkGetFn func(context.Context, *apiv2.NetworkServiceGetRequest) (*apiv2.NetworkServiceGetResponse, error) + + ImageLatestFn func(context.Context, *apiv2.ImageServiceLatestRequest) (*apiv2.ImageServiceLatestResponse, error) +) + +// Client is a configurable mock apiv2 client implemented as a connect client +// interceptor. Set the various handler fields before using it. Unset handlers +// answer with connect.CodeUnimplemented. The handler fields may be reconfigured +// at any time (e.g. between calls in an integration test). +type Client struct { + t *testing.T + + mu sync.RWMutex + + OnMachineGet MachineGetFn + OnMachineCreate MachineCreateFn + OnMachineUpdate MachineUpdateFn + OnMachineList MachineListFn + OnMachineDelete MachineDeleteFn + + OnNetworkGet NetworkGetFn + + OnImageLatest ImageLatestFn + + apiv2 apiv2client.Client +} + +// New creates a mock apiv2 client backed by a connect client interceptor. +func New(t *testing.T) *Client { + return &Client{t: t} +} + +// Client returns the apiv2 client that can be passed to the ControllerConfig. +// It is constructed lazily so that the returned client is always wired with this +// mock as its interceptor. +func (m *Client) Client() apiv2client.Client { + m.mu.RLock() + c := m.apiv2 + m.mu.RUnlock() + if c != nil { + return c + } + + m.mu.Lock() + defer m.mu.Unlock() + if m.apiv2 != nil { + return m.apiv2 + } + + c, err := apiv2client.New(&apiv2client.DialConfig{ + BaseURL: "http://localhost", + Interceptors: []connect.Interceptor{m}, + }) + if err != nil { + m.t.Fatalf("unable to create mock apiv2 client: %v", err) + } + m.apiv2 = c + return c +} + +// WrapUnary implements connect.UnaryInterceptorClient. It dispatches the call to +// the configured handler based on the connect procedure, or returns +// connect.CodeUnimplemented when no handler is set for the call. +func (m *Client) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc { + return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + m.mu.RLock() + defer m.mu.RUnlock() + + var ( + resp connect.AnyResponse + err error + ) + switch req.Spec().Procedure { + case apiv2connect.MachineServiceGetProcedure: + var r *apiv2.MachineServiceGetResponse + if m.OnMachineGet != nil { + r, err = m.OnMachineGet(ctx, req.Any().(*apiv2.MachineServiceGetRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + case apiv2connect.MachineServiceCreateProcedure: + var r *apiv2.MachineServiceCreateResponse + if m.OnMachineCreate != nil { + r, err = m.OnMachineCreate(ctx, req.Any().(*apiv2.MachineServiceCreateRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + case apiv2connect.MachineServiceUpdateProcedure: + var r *apiv2.MachineServiceUpdateResponse + if m.OnMachineUpdate != nil { + r, err = m.OnMachineUpdate(ctx, req.Any().(*apiv2.MachineServiceUpdateRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + case apiv2connect.MachineServiceListProcedure: + var r *apiv2.MachineServiceListResponse + if m.OnMachineList != nil { + r, err = m.OnMachineList(ctx, req.Any().(*apiv2.MachineServiceListRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + case apiv2connect.MachineServiceDeleteProcedure: + var r *apiv2.MachineServiceDeleteResponse + if m.OnMachineDelete != nil { + r, err = m.OnMachineDelete(ctx, req.Any().(*apiv2.MachineServiceDeleteRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + case apiv2connect.NetworkServiceGetProcedure: + var r *apiv2.NetworkServiceGetResponse + if m.OnNetworkGet != nil { + r, err = m.OnNetworkGet(ctx, req.Any().(*apiv2.NetworkServiceGetRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + case apiv2connect.ImageServiceLatestProcedure: + var r *apiv2.ImageServiceLatestResponse + if m.OnImageLatest != nil { + r, err = m.OnImageLatest(ctx, req.Any().(*apiv2.ImageServiceLatestRequest)) + } + if r != nil { + resp = connect.NewResponse(r) + } + default: + return nil, connect.NewError(connect.CodeUnimplemented, nil) + } + + if err != nil { + return nil, err + } + if resp == nil { + return nil, connect.NewError(connect.CodeUnimplemented, nil) + } + return resp, nil + } +} + +// WrapStreamingClient implements connect.UnaryInterceptorClient. The controllers +// only use unary calls, so this is not supported. +func (m *Client) WrapStreamingClient(next connect.StreamingClientFunc) connect.StreamingClientFunc { + m.t.Errorf("metalmock does not support streaming client calls") + return nil +} + +// WrapStreamingHandler implements connect.UnaryInterceptorClient. The controllers +// only use unary calls, so this is not supported. +func (m *Client) WrapStreamingHandler(next connect.StreamingHandlerFunc) connect.StreamingHandlerFunc { + m.t.Errorf("metalmock does not support streaming handler calls") + return nil +} diff --git a/main.go b/main.go index 96e1893..f6705a2 100644 --- a/main.go +++ b/main.go @@ -11,8 +11,7 @@ import ( "github.com/go-logr/logr" - metalgo "github.com/metal-stack/metal-go" - "github.com/metal-stack/metal-lib/pkg/pointer" + apiv2client "github.com/metal-stack/api/go/client" "github.com/metal-stack/metal-lib/pkg/tag" "github.com/metal-stack/v" @@ -36,14 +35,12 @@ import ( "github.com/metal-stack/firewall-controller-manager/controllers/update" ) -const ( - metalAuthHMACEnvVar = "METAL_AUTH_HMAC" -) - func main() { var ( - scheme = helper.MustNewFirewallScheme() - metalURL string + scheme = helper.MustNewFirewallScheme() + metalURL string + tokenfile string + project string logLevel string metricsAddr string @@ -81,7 +78,9 @@ func main() { flag.DurationVar(&safetyBackoff, "safety-backoff", 10*time.Second, "duration after which a resource is getting reconciled at minimum") flag.DurationVar(&progressDeadline, "progress-deadline", 15*time.Minute, "time after which a deployment is considered unhealthy instead of progressing (informational)") flag.DurationVar(&gracefulShutdownTimeout, "graceful-shutdown-timeout", -1, "grace period after which the controller shuts down") - flag.StringVar(&metalURL, "metal-api-url", "", "the url of the metal-stack api") + flag.StringVar(&metalURL, "metal-apiv2-url", "", "the url of the metal-stack apiserver") + flag.StringVar(&tokenfile, "token-file", "", "the path to the token file to authenticate against the metal-stack apiserver") + flag.StringVar(&project, "project", "", "project id of this cluster") flag.StringVar(&clusterID, "cluster-id", "", "id of the cluster this controller is responsible for") flag.StringVar(&shootApiURL, "shoot-api-url", "", "url of the shoot api server, if not provided falls back to single-cluster mode") flag.StringVar(&internalShootApiURL, "internal-shoot-api-url", "", "url of the shoot api server used by this controller, not published in the shoot access status") @@ -112,7 +111,7 @@ func main() { stop = ctrl.SetupSignalHandler() ) - mclient, err := getMetalClient(metalURL) + mclient, err := getMetalClient(metalURL, tokenfile) if err != nil { log.Fatalf("unable to create metal client %v", err) } @@ -179,15 +178,9 @@ func main() { shootApiURL = seedMgr.GetConfig().Host internalShootAccessHelper = helper.NewSingleClusterModeHelper(seedMgr.GetConfig()) - if err != nil { - log.Fatalf("unable to create shoot helper %v", err) - } l.Info("running in single-cluster mode") } else { internalShootAccessHelper = helper.NewShootAccessHelper(seedClient, internalShootAccess) - if err != nil { - log.Fatalf("unable to create shoot helper %v", err) - } l.Info("running in split-cluster mode (seed and shoot client)") } @@ -238,7 +231,7 @@ func main() { v2.FirewallShootNamespace: {}, }, }, - GracefulShutdownTimeout: pointer.Pointer(time.Duration(0)), + GracefulShutdownTimeout: new(time.Duration(0)), }) if err != nil { log.Fatalf("unable to start firewall-controller-manager-monitor %v", err) @@ -259,6 +252,7 @@ func main() { ShootAccessHelper: internalShootAccessHelper, Metal: mclient, ClusterTag: fmt.Sprintf("%s=%s", tag.ClusterID, clusterID), + Project: project, SafetyBackoff: safetyBackoff, ProgressDeadline: progressDeadline, FirewallHealthTimeout: firewallHealthTimeout, @@ -310,19 +304,21 @@ func main() { } } -func getMetalClient(url string) (metalgo.Client, error) { - hmac := os.Getenv(metalAuthHMACEnvVar) - +func getMetalClient(url, tokenfile string) (apiv2client.Client, error) { if url == "" { return nil, fmt.Errorf("metal api url is required") } - if hmac == "" { - return nil, fmt.Errorf("environment variable %q is required", metalAuthHMACEnvVar) + if tokenfile == "" { + return nil, fmt.Errorf("tokenfile is required") } - client, err := metalgo.NewDriver(url, "", hmac) + client, err := apiv2client.New(&apiv2client.DialConfig{ + BaseURL: url, + TokenFile: tokenfile, + }) + if err != nil { - return nil, fmt.Errorf("unable to initialize metal ccm:%w", err) + return nil, err } return client, nil