diff --git a/cloud/services/networkinterfaces/ipam.go b/cloud/services/networkinterfaces/ipam.go new file mode 100644 index 00000000..25904d63 --- /dev/null +++ b/cloud/services/networkinterfaces/ipam.go @@ -0,0 +1,134 @@ +/* +Copyright 2024 The Kubernetes Authors. +Portions Copyright © Microsoft Corporation. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package networkinterfaces + +import ( + "context" + + "github.com/Azure/go-autorest/autorest/to" + "github.com/go-logr/logr" + "github.com/microsoft/moc-sdk-for-go/services/network" + "go.uber.org/multierr" + + ipam "dev.azure.com/msazure/msk8s/_git/azstackhci-operator.git/pkg/ipam" + "github.com/microsoft/cluster-api-provider-azurestackhci/cloud/scope" + "github.com/microsoft/cluster-api-provider-azurestackhci/cloud/telemetry" +) + +// CAPHTelemetryWriter implements ipam.IPAMTelemetryWriter for CAPH. +type CAPHTelemetryWriter struct { + vmScope *scope.VirtualMachineScope +} + +// WriteIPAMOperationLog implements ipam.IPAMTelemetryWriter. +func (w *CAPHTelemetryWriter) WriteIPAMOperationLog(logger logr.Logger, operation ipam.IPAMOperation, claimName string, params map[string]string, err error) { + var telemetryOp telemetry.Operation + switch operation { + case ipam.OperationCreate, ipam.OperationSync: + telemetryOp = telemetry.Create + case ipam.OperationDelete: + telemetryOp = telemetry.Delete + case ipam.OperationGet: + telemetryOp = telemetry.Get + default: + telemetryOp = telemetry.Create + } + + telemetry.WriteMocOperationLog( + logger, + telemetryOp, + w.vmScope.GetCustomResourceTypeWithName(), + telemetry.IPAddressClaim, + telemetry.GenerateMocResourceName(w.vmScope.GetResourceGroup(), claimName), + params, + err, + ) +} + +// IPAMService wraps ipam.IPAMService for CAPH-specific functionality. +type IPAMService struct { + *ipam.IPAMService +} + +// NewIPAMService creates a new IPAM service instance. +func NewIPAMService(vmscope *scope.VirtualMachineScope) *IPAMService { + logger := vmscope.GetLogger() + + config := ipam.IPAMServiceConfig{ + Client: vmscope.Client(), + Logger: logger, + Namespace: vmscope.Namespace(), + VnetName: vmscope.VnetName(), + CloudFqdn: vmscope.CloudAgentFqdn, + Authorizer: vmscope.Authorizer, + TelemetryWriter: &CAPHTelemetryWriter{vmScope: vmscope}, + ClusterName: vmscope.ClusterName(), + CreatorID: ipam.IPClaimCreatorCAPH, + Owner: vmscope.AzureStackHCIVirtualMachine, + } + + return &IPAMService{ + IPAMService: ipam.NewIPAMService(config), + } +} + +// AllocateNicIPClaim allocates IPClaims for all IP configurations on a NIC. +func (s *IPAMService) AllocateNicIPClaim(ctx context.Context, mocNic network.Interface, staticIPAddress string) error { + var errs error + for index, ipconfig := range *mocNic.IPConfigurations { + claimName := ipam.GenerateNICIPClaimName(*mocNic.Name, index) + if allocatedIP, err := s.AllocateIP(ctx, claimName, staticIPAddress); err != nil { + errs = multierr.Append(errs, err) + } else { + ipconfig.InterfaceIPConfigurationPropertiesFormat.PrivateIPAddress = to.StringPtr(allocatedIP) + } + } + return errs +} + +// SyncNicIPClaim syncs IPClaims for all IP configurations on a NIC. +func (s *IPAMService) SyncNicIPClaim(ctx context.Context, mocNic network.Interface) error { + var errs error + for index, ipconfig := range *mocNic.IPConfigurations { + claimName := ipam.GenerateNICIPClaimName(*mocNic.Name, index) + if err := s.SyncIPClaim(ctx, claimName, *(ipconfig.InterfaceIPConfigurationPropertiesFormat.PrivateIPAddress)); err != nil { + errs = multierr.Append(errs, err) + } + } + return errs +} + +// DeleteNicIPClaim deletes IPClaims for all IP configurations on a NIC. +func (s *IPAMService) DeleteNicIPClaim(ctx context.Context, nicSpec *Spec) error { + var errs error + if len(nicSpec.IPConfigurations) == 0 { + claimName := ipam.GenerateNICIPClaimName(nicSpec.Name, 0) + if errs = s.DeleteIPClaim(ctx, claimName); errs != nil { + return errs + } + return nil + } + + for index := range nicSpec.IPConfigurations { + claimName := ipam.GenerateNICIPClaimName(nicSpec.Name, index) + if err := s.DeleteIPClaim(ctx, claimName); err != nil { + errs = multierr.Append(errs, err) + } + } + return errs +} diff --git a/cloud/services/networkinterfaces/networkinterfaces.go b/cloud/services/networkinterfaces/networkinterfaces.go index aee910ce..893b63c9 100644 --- a/cloud/services/networkinterfaces/networkinterfaces.go +++ b/cloud/services/networkinterfaces/networkinterfaces.go @@ -19,12 +19,15 @@ package networkinterfaces import ( "context" + "time" "github.com/Azure/go-autorest/autorest/to" azurestackhci "github.com/microsoft/cluster-api-provider-azurestackhci/cloud" "github.com/microsoft/cluster-api-provider-azurestackhci/cloud/telemetry" "github.com/microsoft/moc-sdk-for-go/services/network" + mocerrors "github.com/microsoft/moc/pkg/errors" "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/util/wait" ) // Spec specification for ip configuration @@ -44,6 +47,7 @@ type Spec struct { MacAddress string BackendPoolNames []string IPConfigurations IPConfigurations + IPAMService *IPAMService } // Get provides information about a network interface. @@ -67,12 +71,19 @@ func (s *Service) Reconcile(ctx context.Context, spec interface{}) error { return errors.New("invalid network interface specification") } - if _, err := s.Get(ctx, nicSpec); err == nil { + if nic, err := s.Get(ctx, nicSpec); err == nil { // Nic already exists, no update supported for now + // Sync back to IPAM to ensure claim exists + s.Scope.GetLogger().Info("Nic exists, attempting to sync IPClaim", "name", nicSpec.Name) + mocNic := nic.(network.Interface) + if err := s.IPAMService.SyncNicIPClaim(ctx, mocNic); err != nil { + s.Scope.GetLogger().Info("Failed to sync IPClaim during reconcile", "error", err) + // Non-blocking - don't fail NIC reconcile + } return nil } - logger := s.Scope.GetLogger() + logger := s.Scope.GetLogger() nicConfig := &network.InterfaceIPConfigurationPropertiesFormat{} nicConfig.Subnet = &network.APIEntityReference{ ID: to.StringPtr(nicSpec.VnetName), @@ -101,7 +112,6 @@ func (s *Service) Reconcile(ctx context.Context, spec interface{}) error { if len(nicSpec.IPConfigurations) > 0 { logger.Info("Adding ipconfigurations to nic ", "len", len(nicSpec.IPConfigurations), "name", nicSpec.Name) for _, ipconfig := range nicSpec.IPConfigurations { - networkIPConfig := network.InterfaceIPConfiguration{ Name: &ipconfig.Name, InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{ @@ -127,20 +137,75 @@ func (s *Service) Reconcile(ctx context.Context, spec interface{}) error { *networkInterface.IPConfigurations = append(*networkInterface.IPConfigurations, networkIPConfig) } - _, err := s.Client.CreateOrUpdate(ctx, + // assign ipam IP to the moc nic object. + if err := s.IPAMService.AllocateNicIPClaim(ctx, networkInterface, nicSpec.StaticIPAddress); err != nil { + logger.Error(err, "Failed to allocate IPClaim for network interface", "name", nicSpec.Name) + } + + logger.Info("creating network interface ", "name", nicSpec.Name) + + createdNic, err := s.Client.CreateOrUpdate(ctx, s.Scope.GetResourceGroup(), nicSpec.Name, &networkInterface) telemetry.WriteMocOperationLog(s.Scope.GetLogger(), telemetry.CreateOrUpdate, s.Scope.GetCustomResourceTypeWithName(), telemetry.NetworkInterface, telemetry.GenerateMocResourceName(s.Scope.GetResourceGroup(), nicSpec.Name), &networkInterface, err) if err != nil { - return errors.Wrapf(err, "failed to create network interface %s in resource group %s", nicSpec.Name, s.Scope.GetResourceGroup()) + if s.shouldRetryIfIPConflict(err, nicSpec) { + if createdNic, err = s.handleIPAddressConflictRetry(ctx, nicSpec, &networkInterface); err != nil { + return errors.Wrapf(err, "failed to retry create with network interface %s in resource group %s", nicSpec.Name, s.Scope.GetResourceGroup()) + } + } else { + return errors.Wrapf(err, "failed to create network interface %s in resource group %s", nicSpec.Name, s.Scope.GetResourceGroup()) + } + } + + if err := s.IPAMService.SyncNicIPClaim(ctx, *createdNic); err != nil { + logger.Info("Failed to sync IPClaim after NIC creation", "error", err) + // Non-blocking - don't fail NIC reconcile } logger.Info("successfully created network interface ", "name", nicSpec.Name) return err } +// isIPConflictError checks if the error indicates an IP address conflict that should trigger a retry +func (s *Service) shouldRetryIfIPConflict(err error, nicSpec *Spec) bool { + // user specified static IP, no need to retry + if err == nil || nicSpec.StaticIPAddress != "" { + return false + } + + // Check for the specific error pattern indicating IP address conflict + return mocerrors.IsAlreadySet(err) +} + +func (s *Service) handleIPAddressConflictRetry(ctx context.Context, vnicSpec *Spec, networkInterface *network.Interface) (*network.Interface, error) { + logger := s.Scope.GetLogger() + logger.Info("IP allocated by IPAM is already taken in Moc, retrying", "Conflicted IP", (*networkInterface.IPConfigurations)[0].InterfaceIPConfigurationPropertiesFormat.PrivateIPAddress) + + // Remove the failed mocnetworkinterface + if err := s.Delete(ctx, vnicSpec); err != nil { + return nil, err + } + + for _, ipconfig := range *networkInterface.IPConfigurations { + ipconfig.InterfaceIPConfigurationPropertiesFormat.PrivateIPAddress = nil + } + + logger.Info("Creating network interface with empty PrivateIPAddress") + // Recreate the mocnetworkinterface without the IPAM allocated IP + createdNic, err := s.Client.CreateOrUpdate(ctx, + s.Scope.GetResourceGroup(), + vnicSpec.Name, + networkInterface) + + telemetry.WriteMocOperationLog(s.Scope.GetLogger(), telemetry.CreateOrUpdate, s.Scope.GetCustomResourceTypeWithName(), telemetry.NetworkInterface, + telemetry.GenerateMocResourceName(s.Scope.GetResourceGroup(), vnicSpec.Name), &networkInterface, err) + + return createdNic, err +} + // Delete deletes the network interface with the provided name. func (s *Service) Delete(ctx context.Context, spec interface{}) error { telemetry.WriteMocInfoLog(ctx, s.Scope) @@ -150,17 +215,52 @@ func (s *Service) Delete(ctx context.Context, spec interface{}) error { } logger := s.Scope.GetLogger() logger.Info("deleting nic", "name", nicSpec.Name) + defer func() { + if err := s.IPAMService.DeleteNicIPClaim(ctx, nicSpec); err != nil { + logger.Error(err, "failed to delete IPAM claim for nic", "name", nicSpec.Name) + } + }() + err := s.Client.Delete(ctx, s.Scope.GetResourceGroup(), nicSpec.Name) telemetry.WriteMocOperationLog(logger, telemetry.Delete, s.Scope.GetCustomResourceTypeWithName(), telemetry.NetworkInterface, telemetry.GenerateMocResourceName(s.Scope.GetResourceGroup(), nicSpec.Name), nil, err) if err != nil && azurestackhci.ResourceNotFound(err) { - // already deleted return nil } if err != nil { return errors.Wrapf(err, "failed to delete network interface %s in resource group %s", nicSpec.Name, s.Scope.GetResourceGroup()) } + err = s.ensureNicDeleted(ctx, nicSpec) + if err != nil { + return errors.Wrapf(err, "timed out waiting for deletion of network interface %s in resource group %s", nicSpec.Name, s.Scope.GetResourceGroup()) + } + logger.Info("successfully deleted nic", "name", nicSpec.Name) return err } + +// ensureNicDeleted ensures the network interface is deleted by polling Get with a 5 second timeout. +func (s *Service) ensureNicDeleted(ctx context.Context, nicSpec *Spec) error { + logger := s.Scope.GetLogger() + + pollErr := wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) { + _, err := s.Get(ctx, nicSpec) + if err != nil { + if azurestackhci.ResourceNotFound(err) { + logger.Info("nic is deleted", "name", nicSpec.Name) + return true, nil // Deletion complete + } + logger.Error(err, "failed to get nic", "name", nicSpec.Name) + return false, err + } + logger.Info("nic still exists, waiting for deletion", "name", nicSpec.Name) + return false, nil // Continue polling + }) + + if pollErr != nil { + return errors.Wrapf(pollErr, "failed waiting for nic %s to be deleted", nicSpec.Name) + } + + return nil +} diff --git a/cloud/services/networkinterfaces/service.go b/cloud/services/networkinterfaces/service.go index b054bac5..4ce40f7a 100644 --- a/cloud/services/networkinterfaces/service.go +++ b/cloud/services/networkinterfaces/service.go @@ -29,8 +29,9 @@ var _ azurestackhci.Service = (*Service)(nil) // Service provides operations on network interfaces type Service struct { - Client networkinterface.InterfaceClient - Scope scope.ScopeInterface + Client networkinterface.InterfaceClient + Scope scope.ScopeInterface + IPAMService *IPAMService } // getNetworkInterfacesClient creates a new network interfaces client. @@ -40,9 +41,10 @@ func getNetworkInterfacesClient(cloudAgentFqdn string, authorizer auth.Authorize } // NewService creates a new network interfaces service. -func NewService(scope scope.ScopeInterface) *Service { +func NewService(scope scope.ScopeInterface, ipamSvc *IPAMService) *Service { return &Service{ - Client: getNetworkInterfacesClient(scope.GetCloudAgentFqdn(), scope.GetAuthorizer()), - Scope: scope, + Client: getNetworkInterfacesClient(scope.GetCloudAgentFqdn(), scope.GetAuthorizer()), + Scope: scope, + IPAMService: ipamSvc, } } diff --git a/cloud/services/virtualmachines/virtualmachines.go b/cloud/services/virtualmachines/virtualmachines.go index 383c0a3e..b8f8cdb3 100644 --- a/cloud/services/virtualmachines/virtualmachines.go +++ b/cloud/services/virtualmachines/virtualmachines.go @@ -92,7 +92,7 @@ func (s *Service) Reconcile(ctx context.Context, spec interface{}) error { logger := s.Scope.GetLogger() logger.Info("getting nic", "nic", vmSpec.NICName) - nicInterface, err := networkinterfaces.NewService(s.Scope).Get(ctx, &networkinterfaces.Spec{Name: vmSpec.NICName}) + nicInterface, err := networkinterfaces.NewService(s.Scope, nil).Get(ctx, &networkinterfaces.Spec{Name: vmSpec.NICName}) if err != nil { return err } diff --git a/cloud/telemetry/logutils.go b/cloud/telemetry/logutils.go index 87194aca..3b47088e 100644 --- a/cloud/telemetry/logutils.go +++ b/cloud/telemetry/logutils.go @@ -20,6 +20,7 @@ const ( VipPool MocResourceType = "VipPool" VirtualNetwork MocResourceType = "VirtualNetwork" NetworkInterface MocResourceType = "NetworkInterface" + IPAddressClaim MocResourceType = "IPAddressClaim" Disk MocResourceType = "Disk" VirtualMachine MocResourceType = "VirtualMachine" KeyVault MocResourceType = "KeyVault" diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 5ed0ec4e..437559ef 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -39,6 +39,7 @@ import ( "k8s.io/klog/v2" "k8s.io/klog/v2/klogr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1" "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/util/record" ctrl "sigs.k8s.io/controller-runtime" @@ -61,6 +62,7 @@ func init() { _ = clientgoscheme.AddToScheme(scheme) _ = clusterv1.AddToScheme(scheme) _ = infrav1beta1.AddToScheme(scheme) + _ = ipamv1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index a2854975..c122f133 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -79,3 +79,23 @@ rules: - get - patch - update +- apiGroups: + - ipam.cluster.x-k8s.io + resources: + - ipaddressclaims + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - ipam.cluster.x-k8s.io + resources: + - ipaddresses + verbs: + - get + - list + - watch diff --git a/controllers/azurestackhcicluster_controller.go b/controllers/azurestackhcicluster_controller.go index 57735780..5bfdd368 100644 --- a/controllers/azurestackhcicluster_controller.go +++ b/controllers/azurestackhcicluster_controller.go @@ -157,11 +157,11 @@ func (r *AzureStackHCIClusterReconciler) reconcileNormal(clusterScope *scope.Clu if err != nil { switch mocerrors.GetErrorCode(err) { case mocerrors.OutOfMemory.Error(): - conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.OutOfMemoryReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.OutOfMemoryReason, clusterv1.ConditionSeverityError, "%s", err.Error()) case mocerrors.OutOfCapacity.Error(): - conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.OutOfCapacityReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.OutOfCapacityReason, clusterv1.ConditionSeverityError, "%s", err.Error()) default: - conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.ClusterReconciliationFailedReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.ClusterReconciliationFailedReason, clusterv1.ConditionSeverityError, "%s", err.Error()) } wrappedErr := errors.Wrap(err, "failed to reconcile cluster services") @@ -200,7 +200,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileDelete(clusterScope *scope.Clu if err != nil { wrappedErr := errors.Wrapf(err, "unable to list AzureStackHCIMachines part of AzureStackHCIClusters %s/%s", clusterScope.AzureStackHCICluster.Namespace, clusterScope.AzureStackHCICluster.Name) r.Recorder.Eventf(azureStackHCICluster, corev1.EventTypeWarning, "FailureListMachinesInCluster", wrappedErr.Error()) - conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, wrappedErr } @@ -210,7 +210,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileDelete(clusterScope *scope.Clu if err != nil { wrappedErr := errors.Wrapf(err, "failed to delete orphaned AzureStackHCIMachines part of AzureStackHCIClusters %s/%s", clusterScope.AzureStackHCICluster.Namespace, clusterScope.AzureStackHCICluster.Name) r.Recorder.Eventf(azureStackHCICluster, corev1.EventTypeWarning, "FailureListMachinesInCluster", wrappedErr.Error()) - conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, wrappedErr } @@ -240,7 +240,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileDelete(clusterScope *scope.Clu if err := newAzureStackHCIClusterReconciler(clusterScope).Delete(); err != nil { wrappedErr := errors.Wrapf(err, "error deleting AzureStackHCICluster %s/%s", azureStackHCICluster.Namespace, azureStackHCICluster.Name) r.Recorder.Eventf(azureStackHCICluster, corev1.EventTypeWarning, "FailureClusterDelete", wrappedErr.Error()) - conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(azureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, wrappedErr } @@ -334,7 +334,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileAzureStackHCILoadBalancer(clus } if err != nil { if !apierrors.IsAlreadyExists(err) { - conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.LoadBalancerProvisioningReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, infrav1.LoadBalancerProvisioningReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return false, err } } @@ -342,7 +342,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileAzureStackHCILoadBalancer(clus // Wait for the load balancer to be fully provisioned if conditions.IsFalse(azureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition) { cond := conditions.Get(azureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition) - conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, cond.Reason, cond.Severity, cond.Message) + conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, cond.Reason, cond.Severity, "%s", cond.Message) return false, nil } @@ -381,7 +381,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileDeleteAzureStackHCILoadBalance infrav1util.CopyCorrelationID(clusterScope.AzureStackHCICluster, azureStackHCILoadBalancer) if err := r.Client.Update(clusterScope.Context, azureStackHCILoadBalancer); err != nil { if !apierrors.IsNotFound(err) { - conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return errors.Wrapf(err, "Failed to update AzureStackHCILoadBalancer %s", azureStackHCILoadBalancerName) } } @@ -396,7 +396,7 @@ func (r *AzureStackHCIClusterReconciler) reconcileDeleteAzureStackHCILoadBalance err) if err != nil { if !apierrors.IsNotFound(err) { - conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(clusterScope.AzureStackHCICluster, infrav1.NetworkInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return errors.Wrapf(err, "Failed to delete AzureStackHCILoadBalancer %s", azureStackHCILoadBalancerName) } } diff --git a/controllers/azurestackhciloadbalancer_controller.go b/controllers/azurestackhciloadbalancer_controller.go index c9c1d595..aae1bed5 100644 --- a/controllers/azurestackhciloadbalancer_controller.go +++ b/controllers/azurestackhciloadbalancer_controller.go @@ -188,7 +188,7 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileNormal(lbs *scope.LoadBal result, err := r.reconcileVirtualMachines(lbs, clusterScope) if err != nil { r.Recorder.Eventf(lbs.AzureStackHCILoadBalancer, corev1.EventTypeWarning, "FailureReconcileLBMachines", errors.Wrapf(err, "Failed to reconcile LoadBalancer machines").Error()) - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerMachineReconciliationFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerMachineReconciliationFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, err } @@ -197,11 +197,11 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileNormal(lbs *scope.LoadBal if err != nil { switch mocerrors.GetErrorCode(err) { case mocerrors.OutOfMemory.Error(): - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.OutOfMemoryReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.OutOfMemoryReason, clusterv1.ConditionSeverityError, "%s", err.Error()) case mocerrors.OutOfCapacity.Error(): - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.OutOfCapacityReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.OutOfCapacityReason, clusterv1.ConditionSeverityError, "%s", err.Error()) default: - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerServiceReconciliationFailedReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerServiceReconciliationFailedReason, clusterv1.ConditionSeverityError, "%s", err.Error()) } r.Recorder.Eventf(lbs.AzureStackHCILoadBalancer, corev1.EventTypeWarning, "FailureReconcileLB", errors.Wrapf(err, "Failed to reconcile LoadBalancer service").Error()) @@ -212,7 +212,7 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileNormal(lbs *scope.LoadBal err := r.reconcileLoadBalancerServiceStatus(lbs, clusterScope) if err != nil { r.Recorder.Eventf(lbs.AzureStackHCILoadBalancer, corev1.EventTypeWarning, "FailureReconcileLBStatus", errors.Wrapf(err, "Failed to reconcile LoadBalancer service status").Error()) - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerServiceStatusFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerServiceStatusFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, err } if lbs.Address() == "" { @@ -294,13 +294,13 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileDelete(lbs *scope.LoadBal if err := r.reconcileDeleteLoadBalancerService(lbs, clusterScope); err != nil { r.Recorder.Eventf(lbs.AzureStackHCILoadBalancer, corev1.EventTypeWarning, "FailureDeleteLoadBalancer", errors.Wrapf(err, "Error deleting AzureStackHCILoadBalancer %s", lbs.Name()).Error()) - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, err } if err := r.reconcileDeleteVirtualMachines(lbs, clusterScope); err != nil { r.Recorder.Eventf(lbs.AzureStackHCILoadBalancer, corev1.EventTypeWarning, "FailureDeleteLoadBalancerMachines", errors.Wrapf(err, "Error deleting machines for AzureStackHCILoadBalancer %s", lbs.Name()).Error()) - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, err } @@ -351,7 +351,7 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileStatus(lbs *scope.LoadBal if conditions.IsFalse(lb, infrav1.LoadBalancerReplicasReadyCondition) { if *conditions.GetSeverity(lb, infrav1.LoadBalancerReplicasReadyCondition) == clusterv1.ConditionSeverityError { cond := conditions.Get(lb, infrav1.LoadBalancerReplicasReadyCondition) - conditions.MarkFalse(lb, infrav1.LoadBalancerInfrastructureReadyCondition, cond.Reason, cond.Severity, cond.Message) + conditions.MarkFalse(lb, infrav1.LoadBalancerInfrastructureReadyCondition, cond.Reason, cond.Severity, "%s", cond.Message) } if conditions.GetReason(lb, infrav1.LoadBalancerReplicasReadyCondition) == infrav1.LoadBalancerReplicasUpgradingReason { diff --git a/controllers/azurestackhciloadbalancer_virtualmachine.go b/controllers/azurestackhciloadbalancer_virtualmachine.go index 602a86b0..4c318362 100644 --- a/controllers/azurestackhciloadbalancer_virtualmachine.go +++ b/controllers/azurestackhciloadbalancer_virtualmachine.go @@ -50,7 +50,7 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileVirtualMachines(lbs *scop if conditions.IsFalse(vm, infrav1.VMRunningCondition) { cond := conditions.Get(vm, infrav1.VMRunningCondition) if cond.Severity == clusterv1.ConditionSeverityError { - conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerReplicasReadyCondition, cond.Reason, cond.Severity, cond.Message) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerReplicasReadyCondition, cond.Reason, cond.Severity, "%s", cond.Message) return reconcile.Result{}, nil } } diff --git a/controllers/azurestackhcivirtualmachine_controller.go b/controllers/azurestackhcivirtualmachine_controller.go index 6ae5d7a4..96834f97 100644 --- a/controllers/azurestackhcivirtualmachine_controller.go +++ b/controllers/azurestackhcivirtualmachine_controller.go @@ -79,6 +79,8 @@ func (r *AzureStackHCIVirtualMachineReconciler) ConstructLogger(req *reconcile.R // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=azurestackhcivirtualmachines,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=azurestackhcivirtualmachines/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddressclaims,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddresses,verbs=get;list;watch // Reconcile reacts to some event on the kubernetes object that the controller has registered to handle func (r *AzureStackHCIVirtualMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { @@ -195,7 +197,7 @@ func (r *AzureStackHCIVirtualMachineReconciler) getOrCreate(virtualMachineScope if err != nil { wrappedErr := errors.Wrapf(err, "Failed to query for AzureStackHCIVirtualMachine %s/%s", virtualMachineScope.Namespace(), virtualMachineScope.Name()) r.Recorder.Eventf(virtualMachineScope.AzureStackHCIVirtualMachine, corev1.EventTypeWarning, "FailureQueryForVM", wrappedErr.Error()) - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.VMNotFoundReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.VMNotFoundReason, clusterv1.ConditionSeverityError, "%s", err.Error()) return nil, err } @@ -206,22 +208,22 @@ func (r *AzureStackHCIVirtualMachineReconciler) getOrCreate(virtualMachineScope if err != nil { switch mocerrors.GetErrorCode(err) { case mocerrors.OutOfMemory.Error(): - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.OutOfMemoryReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.OutOfMemoryReason, clusterv1.ConditionSeverityError, "%s", err.Error()) case mocerrors.OutOfCapacity.Error(): - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.OutOfCapacityReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.OutOfCapacityReason, clusterv1.ConditionSeverityError, "%s", err.Error()) case mocerrors.OutOfNodeCapacity.Error(): - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.OutOfNodeCapacityReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.OutOfNodeCapacityReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) case mocerrors.NotFound.Error(): // "NotFound" fallthrough // Internally, NotFound is a legacy error and returns the error string instead. case moccodes.NotFound.String(): // "Not Found" if mocerrors.IsPathNotFound(err) { - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.PathNotFoundReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.PathNotFoundReason, clusterv1.ConditionSeverityError, "%s", err.Error()) } else { - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.NotFoundReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.NotFoundReason, clusterv1.ConditionSeverityError, "%s", err.Error()) } default: - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.VMProvisionFailedReason, clusterv1.ConditionSeverityError, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, infrav1.VMProvisionFailedReason, clusterv1.ConditionSeverityError, "%s", err.Error()) } wrappedErr := errors.Wrapf(err, "failed to create AzureStackHCIVirtualMachine") @@ -230,6 +232,14 @@ func (r *AzureStackHCIVirtualMachineReconciler) getOrCreate(virtualMachineScope return nil, wrappedErr } r.Recorder.Eventf(virtualMachineScope.AzureStackHCIVirtualMachine, corev1.EventTypeNormal, "SuccessfulCreateVM", "Success creating AzureStackHCIVirtualMachine %s/%s", virtualMachineScope.Namespace(), virtualMachineScope.Name()) + } else { + // calling this here to ensure nic ip claims are created for existing vms as well, this is needed for + // brownfield scenarios where VMs already exist when we introduce IPAM + virtualMachineScope.Info("VM found, reconciling existing VM for Nics", "Name", virtualMachineScope.Name()) + _, err = ams.ReconcileNics() + if err != nil { + return nil, err + } } return vm, nil @@ -243,7 +253,7 @@ func (r *AzureStackHCIVirtualMachineReconciler) reconcileDelete(virtualMachineSc if err := newAzureStackHCIVirtualMachineService(virtualMachineScope).Delete(); err != nil { wrappedErr := errors.Wrapf(err, "error deleting AzureStackHCIVirtualMachine %s/%s", virtualMachineScope.Namespace(), virtualMachineScope.Name()) r.Recorder.Eventf(virtualMachineScope.AzureStackHCIVirtualMachine, corev1.EventTypeWarning, "FailureDeleteVM", wrappedErr.Error()) - conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, err.Error()) + conditions.MarkFalse(virtualMachineScope.AzureStackHCIVirtualMachine, infrav1.VMRunningCondition, clusterv1.DeletionFailedReason, clusterv1.ConditionSeverityWarning, "%s", err.Error()) return reconcile.Result{}, wrappedErr } r.Recorder.Eventf(virtualMachineScope.AzureStackHCIVirtualMachine, corev1.EventTypeNormal, "SuccessfulDeleteVM", "Success deleting AzureStackHCIVirtualMachine %s/%s", virtualMachineScope.Namespace(), virtualMachineScope.Name()) diff --git a/controllers/azurestackhcivirtualmachine_reconciler.go b/controllers/azurestackhcivirtualmachine_reconciler.go index 1c574556..eb5d992d 100644 --- a/controllers/azurestackhcivirtualmachine_reconciler.go +++ b/controllers/azurestackhcivirtualmachine_reconciler.go @@ -43,6 +43,7 @@ const ( // TODO: We should decide if we want to keep this type azureStackHCIVirtualMachineService struct { vmScope *scope.VirtualMachineScope + ipamSvc *networkinterfaces.IPAMService networkInterfacesSvc azurestackhci.Service virtualMachinesSvc azurestackhci.GetterService disksSvc azurestackhci.GetterService @@ -52,16 +53,28 @@ type azureStackHCIVirtualMachineService struct { func newAzureStackHCIVirtualMachineService(vmScope *scope.VirtualMachineScope) *azureStackHCIVirtualMachineService { return &azureStackHCIVirtualMachineService{ vmScope: vmScope, - networkInterfacesSvc: networkinterfaces.NewService(vmScope), + networkInterfacesSvc: networkinterfaces.NewService(vmScope, networkinterfaces.NewIPAMService(vmScope)), virtualMachinesSvc: virtualmachines.NewService(vmScope), disksSvc: disks.NewService(vmScope), } } -// Create creates machine if and only if machine exists, handled by cluster-api -func (s *azureStackHCIVirtualMachineService) Create() (*infrav1.VM, error) { +// ReconcileNics reconciles the network interfaces for a VM +func (s *azureStackHCIVirtualMachineService) ReconcileNics() (string, error) { nicName := azurestackhci.GenerateNICName(s.vmScope.Name()) + var ipconfigs = s.generateIPConfigs() + + nicErr := s.reconcileNetworkInterface(nicName, ipconfigs) + if nicErr != nil { + return "", errors.Wrapf(nicErr, "failed to create nic %s for machine %s", nicName, s.vmScope.Name()) + } + + return nicName, nil +} + +func (s *azureStackHCIVirtualMachineService) generateIPConfigs() networkinterfaces.IPConfigurations { + nicName := azurestackhci.GenerateNICName(s.vmScope.Name()) var ipconfigs networkinterfaces.IPConfigurations if len(s.vmScope.AzureStackHCIVirtualMachine.Spec.NetworkInterfaces) > 0 { @@ -79,10 +92,14 @@ func (s *azureStackHCIVirtualMachineService) Create() (*infrav1.VM, error) { ipconfigs = append(ipconfigs, ipconfig) } } + return ipconfigs +} - nicErr := s.reconcileNetworkInterface(nicName, ipconfigs) - if nicErr != nil { - return nil, errors.Wrapf(nicErr, "failed to create nic %s for machine %s", nicName, s.vmScope.Name()) +// Create creates machine if and only if machine exists, handled by cluster-api +func (s *azureStackHCIVirtualMachineService) Create() (*infrav1.VM, error) { + nicName, err := s.ReconcileNics() + if err != nil { + return nil, err } vm, vmErr := s.createVirtualMachine(nicName) @@ -128,8 +145,9 @@ func (s *azureStackHCIVirtualMachineService) Delete() error { } networkInterfaceSpec := &networkinterfaces.Spec{ - Name: azurestackhci.GenerateNICName(s.vmScope.Name()), - VnetName: s.vmScope.VnetName(), + Name: azurestackhci.GenerateNICName(s.vmScope.Name()), + VnetName: s.vmScope.VnetName(), + IPConfigurations: s.generateIPConfigs(), } err = s.networkInterfacesSvc.Delete(s.vmScope.Context, networkInterfaceSpec) diff --git a/go.mod b/go.mod index 051d6425..7a9665ef 100644 --- a/go.mod +++ b/go.mod @@ -1,29 +1,34 @@ module github.com/microsoft/cluster-api-provider-azurestackhci -go 1.23.0 +go 1.24.4 require ( + //dev.azure.com/msazure/One/_git/azlocal-overlay.git/api v0.0.0 + //dev.azure.com/msazure/msk8s/_git/azstackhci-operator.git v0.11.1-alpha.34 + dev.azure.com/msazure/msk8s/_git/azstackhci-operator.git/pkg/ipam v0.0.0 github.com/Azure/go-autorest/autorest/to v0.4.0 github.com/blang/semver v3.5.1+incompatible - github.com/go-logr/logr v1.4.2 + github.com/go-logr/logr v1.4.3 github.com/golang/mock v1.6.0 - github.com/microsoft/moc v0.25.0 + github.com/microsoft/moc v0.31.1 github.com/microsoft/moc-sdk-for-go v0.24.2 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.36.3 github.com/pkg/errors v0.9.1 github.com/spf13/pflag v1.0.6 - golang.org/x/crypto v0.36.0 - google.golang.org/grpc v1.67.3 - k8s.io/api v0.32.3 - k8s.io/apimachinery v0.32.3 + golang.org/x/crypto v0.44.0 + google.golang.org/grpc v1.72.0 + k8s.io/api v0.32.5 + k8s.io/apimachinery v0.32.5 k8s.io/client-go v0.32.3 k8s.io/klog/v2 v2.130.1 - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 + k8s.io/utils v0.0.0-20241210054802-24370beab758 sigs.k8s.io/cluster-api v1.10.3 sigs.k8s.io/controller-runtime v0.20.4 ) +require go.uber.org/multierr v1.11.0 + require ( github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.29 // indirect @@ -46,10 +51,10 @@ require ( github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect @@ -79,18 +84,17 @@ require ( go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.38.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect - golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.31.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect + golang.org/x/time v0.9.0 // indirect + golang.org/x/tools v0.38.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -98,13 +102,15 @@ require ( k8s.io/cluster-bootstrap v0.32.3 // indirect k8s.io/component-base v0.32.3 // indirect k8s.io/klog v1.0.0 // indirect - k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( + dev.azure.com/msazure/msk8s/_git/azstackhci-operator.git/pkg/ipam => ../azstackhci-operator/pkg/ipam github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.1.0 github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027 github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 diff --git a/go.sum b/go.sum index 8f1be9c4..999f7889 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8 github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -91,8 +91,6 @@ github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4 github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= @@ -103,8 +101,8 @@ 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.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g= github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -143,8 +141,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/microsoft/moc v0.25.0 h1:lgGesosWrJQ9UauTHR9ZXHtaM2YiurgnK514AXCpC9E= -github.com/microsoft/moc v0.25.0/go.mod h1:nvYz7yZT6x+rRx/aEkswVTI2sa8AyAG9mZmWvXHk8cw= +github.com/microsoft/moc v0.31.1 h1:JtmQAKErI4DfDAZHbSF8U1sVg7sRue6PzL3PIZICre4= +github.com/microsoft/moc v0.31.1/go.mod h1:OZ1rc2/qs9AVRKCLfwY0N8R+ZXJlVz5UyWYS5vNH4m0= github.com/microsoft/moc-sdk-for-go v0.24.2 h1:OkBuE/TDeuNlcSJ4z0Ly8C2C5xJHywbkncG2wuiAbhQ= github.com/microsoft/moc-sdk-for-go v0.24.2/go.mod h1:1h3uU5Z3qE5d/x8L+Tw8rS/PPqfb/8HhCG6/qmD5HCA= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -250,8 +248,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -267,8 +265,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -276,8 +274,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -290,30 +288,30 @@ 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.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -323,12 +321,12 @@ gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuB google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -342,12 +340,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= -k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= +k8s.io/api v0.32.5 h1:uqjjsYo1kTJr5NIcoIaP9F+TgXgADH7nKQx91FDAhtk= +k8s.io/api v0.32.5/go.mod h1:bXXFU3fGCZ/eFMZvfHZC69PeGbXEL4zzjuPVzOxHF64= k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= -k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= -k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apimachinery v0.32.5 h1:6We3aJ6crC0ap8EhsEXcgX3LpI6SEjubpiOMXLROwPM= +k8s.io/apimachinery v0.32.5/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8= k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc= k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= @@ -360,19 +358,22 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/cluster-api v1.10.3 h1:7tE5xgQJutisgDyeLzaZ9JhDaHGuG3GjPltsFM89BoA= sigs.k8s.io/cluster-api v1.10.3/go.mod h1:pu1WDn+fdax9aC9ZtDDoXqnO7P3LLjxbKGU/Nzf/DF4= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=