diff --git a/api/v1beta1/machine_webhook.go b/api/v1beta1/machine_webhook.go index 4a21872eaa51..6aa9b5f25b9c 100644 --- a/api/v1beta1/machine_webhook.go +++ b/api/v1beta1/machine_webhook.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/cluster-api/util/version" ) @@ -71,22 +72,22 @@ func (m *Machine) Default() { } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *Machine) ValidateCreate() error { - return m.validate(nil) +func (m *Machine) ValidateCreate() (admission.Warnings, error) { + return nil, m.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *Machine) ValidateUpdate(old runtime.Object) error { +func (m *Machine) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { oldM, ok := old.(*Machine) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a Machine but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Machine but got a %T", old)) } - return m.validate(oldM) + return nil, m.validate(oldM) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *Machine) ValidateDelete() error { - return nil +func (m *Machine) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (m *Machine) validate(old *Machine) error { diff --git a/api/v1beta1/machine_webhook_test.go b/api/v1beta1/machine_webhook_test.go index 485330aa3355..079ecb1e78eb 100644 --- a/api/v1beta1/machine_webhook_test.go +++ b/api/v1beta1/machine_webhook_test.go @@ -79,11 +79,15 @@ func TestMachineBootstrapValidation(t *testing.T) { Spec: MachineSpec{Bootstrap: tt.bootstrap}, } if tt.expectErr { - g.Expect(m.ValidateCreate()).NotTo(Succeed()) - g.Expect(m.ValidateUpdate(m)).NotTo(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(m.ValidateCreate()).To(Succeed()) - g.Expect(m.ValidateUpdate(m)).To(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).ToNot(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).ToNot(HaveOccurred()) } }) } @@ -137,11 +141,15 @@ func TestMachineNamespaceValidation(t *testing.T) { } if tt.expectErr { - g.Expect(m.ValidateCreate()).NotTo(Succeed()) - g.Expect(m.ValidateUpdate(m)).NotTo(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(m.ValidateCreate()).To(Succeed()) - g.Expect(m.ValidateUpdate(m)).To(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).ToNot(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).ToNot(HaveOccurred()) } }) } @@ -185,10 +193,11 @@ func TestMachineClusterNameImmutable(t *testing.T) { }, } + _, err := newMachine.ValidateUpdate(oldMachine) if tt.expectErr { - g.Expect(newMachine.ValidateUpdate(oldMachine)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(newMachine.ValidateUpdate(oldMachine)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -239,11 +248,15 @@ func TestMachineVersionValidation(t *testing.T) { } if tt.expectErr { - g.Expect(m.ValidateCreate()).NotTo(Succeed()) - g.Expect(m.ValidateUpdate(m)).NotTo(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(m.ValidateCreate()).To(Succeed()) - g.Expect(m.ValidateUpdate(m)).To(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).ToNot(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).ToNot(HaveOccurred()) } }) } diff --git a/api/v1beta1/machinedeployment_webhook.go b/api/v1beta1/machinedeployment_webhook.go index f737c8fd105d..797b3b97e25b 100644 --- a/api/v1beta1/machinedeployment_webhook.go +++ b/api/v1beta1/machinedeployment_webhook.go @@ -31,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/klog/v2" "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" @@ -57,10 +56,8 @@ var _ webhook.Validator = &MachineDeployment{} // MachineDeploymentDefaulter creates a new CustomDefaulter for MachineDeployments. func MachineDeploymentDefaulter(scheme *runtime.Scheme) webhook.CustomDefaulter { - // Note: The error return parameter is always nil and will be dropped with the next CR release. - decoder, _ := admission.NewDecoder(scheme) return &machineDeploymentDefaulter{ - decoder: decoder, + decoder: admission.NewDecoder(scheme), } } @@ -167,22 +164,22 @@ func (webhook *machineDeploymentDefaulter) Default(ctx context.Context, obj runt } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineDeployment) ValidateCreate() error { - return m.validate(nil) +func (m *MachineDeployment) ValidateCreate() (admission.Warnings, error) { + return nil, m.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineDeployment) ValidateUpdate(old runtime.Object) error { +func (m *MachineDeployment) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { oldMD, ok := old.(*MachineDeployment) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a MachineDeployment but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachineDeployment but got a %T", old)) } - return m.validate(oldMD) + return nil, m.validate(oldMD) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineDeployment) ValidateDelete() error { - return nil +func (m *MachineDeployment) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (m *MachineDeployment) validate(old *MachineDeployment) error { @@ -302,8 +299,7 @@ func calculateMachineDeploymentReplicas(ctx context.Context, oldMD *MachineDeplo return *newMD.Spec.Replicas, nil } - // TODO(sbueringer): drop this with the next CR version that adds the MD key automatically. - log := ctrl.LoggerFrom(ctx).WithValues("MachineDeployment", klog.KObj(newMD)) + log := ctrl.LoggerFrom(ctx) // If both autoscaler annotations are set, use them to calculate the default value. minSizeString, hasMinSizeAnnotation := newMD.Annotations[AutoscalerMinSizeAnnotation] diff --git a/api/v1beta1/machinedeployment_webhook_test.go b/api/v1beta1/machinedeployment_webhook_test.go index dee64b100691..e5059601766f 100644 --- a/api/v1beta1/machinedeployment_webhook_test.go +++ b/api/v1beta1/machinedeployment_webhook_test.go @@ -393,11 +393,15 @@ func TestMachineDeploymentValidation(t *testing.T) { }, } if tt.expectErr { - g.Expect(md.ValidateCreate()).NotTo(Succeed()) - g.Expect(md.ValidateUpdate(md)).NotTo(Succeed()) + _, err := md.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = md.ValidateUpdate(md) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(md.ValidateCreate()).To(Succeed()) - g.Expect(md.ValidateUpdate(md)).To(Succeed()) + _, err := md.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = md.ValidateUpdate(md) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -452,11 +456,15 @@ func TestMachineDeploymentVersionValidation(t *testing.T) { } if tt.expectErr { - g.Expect(md.ValidateCreate()).NotTo(Succeed()) - g.Expect(md.ValidateUpdate(md)).NotTo(Succeed()) + _, err := md.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = md.ValidateUpdate(md) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(md.ValidateCreate()).To(Succeed()) - g.Expect(md.ValidateUpdate(md)).To(Succeed()) + _, err := md.ValidateCreate() + g.Expect(err).ToNot(HaveOccurred()) + _, err = md.ValidateUpdate(md) + g.Expect(err).ToNot(HaveOccurred()) } }) } @@ -499,10 +507,11 @@ func TestMachineDeploymentClusterNameImmutable(t *testing.T) { }, } + _, err := newMD.ValidateUpdate(oldMD) if tt.expectErr { - g.Expect(newMD.ValidateUpdate(oldMD)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(newMD.ValidateUpdate(oldMD)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -530,18 +539,21 @@ func defaultValidateTestCustomDefaulter(object admission.Validator, customDefaul t.Run("validate-on-create", func(t *testing.T) { g := NewWithT(t) g.Expect(customDefaulter.Default(ctx, createCopy)).To(Succeed()) - g.Expect(createCopy.ValidateCreate()).To(Succeed()) + _, err := createCopy.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) }) t.Run("validate-on-update", func(t *testing.T) { g := NewWithT(t) g.Expect(customDefaulter.Default(ctx, defaultingUpdateCopy)).To(Succeed()) g.Expect(customDefaulter.Default(ctx, updateCopy)).To(Succeed()) - g.Expect(defaultingUpdateCopy.ValidateUpdate(updateCopy)).To(Succeed()) + _, err := defaultingUpdateCopy.ValidateUpdate(updateCopy) + g.Expect(err).NotTo(HaveOccurred()) }) t.Run("validate-on-delete", func(t *testing.T) { g := NewWithT(t) g.Expect(customDefaulter.Default(ctx, deleteCopy)).To(Succeed()) - g.Expect(deleteCopy.ValidateDelete()).To(Succeed()) + _, err := deleteCopy.ValidateDelete() + g.Expect(err).NotTo(HaveOccurred()) }) } } diff --git a/api/v1beta1/machinehealthcheck_webhook.go b/api/v1beta1/machinehealthcheck_webhook.go index d50510eaa2cd..44c596feb5ee 100644 --- a/api/v1beta1/machinehealthcheck_webhook.go +++ b/api/v1beta1/machinehealthcheck_webhook.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) var ( @@ -84,22 +85,22 @@ func (m *MachineHealthCheck) Default() { } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineHealthCheck) ValidateCreate() error { - return m.validate(nil) +func (m *MachineHealthCheck) ValidateCreate() (admission.Warnings, error) { + return nil, m.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineHealthCheck) ValidateUpdate(old runtime.Object) error { +func (m *MachineHealthCheck) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { mhc, ok := old.(*MachineHealthCheck) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a MachineHealthCheck but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachineHealthCheck but got a %T", old)) } - return m.validate(mhc) + return nil, m.validate(mhc) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineHealthCheck) ValidateDelete() error { - return nil +func (m *MachineHealthCheck) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (m *MachineHealthCheck) validate(old *MachineHealthCheck) error { diff --git a/api/v1beta1/machinehealthcheck_webhook_test.go b/api/v1beta1/machinehealthcheck_webhook_test.go index fbb3a7f9a573..c1d5f69bc3ac 100644 --- a/api/v1beta1/machinehealthcheck_webhook_test.go +++ b/api/v1beta1/machinehealthcheck_webhook_test.go @@ -92,11 +92,15 @@ func TestMachineHealthCheckLabelSelectorAsSelectorValidation(t *testing.T) { }, } if tt.expectErr { - g.Expect(mhc.ValidateCreate()).NotTo(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).NotTo(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(mhc.ValidateCreate()).To(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).To(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -160,10 +164,11 @@ func TestMachineHealthCheckClusterNameImmutable(t *testing.T) { }, } + _, err := newMHC.ValidateUpdate(oldMHC) if tt.expectErr { - g.Expect(newMHC.ValidateUpdate(oldMHC)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(newMHC.ValidateUpdate(oldMHC)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -211,11 +216,15 @@ func TestMachineHealthCheckUnhealthyConditions(t *testing.T) { }, } if tt.expectErr { - g.Expect(mhc.ValidateCreate()).NotTo(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).NotTo(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(mhc.ValidateCreate()).To(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).To(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -286,11 +295,15 @@ func TestMachineHealthCheckNodeStartupTimeout(t *testing.T) { } if tt.expectErr { - g.Expect(mhc.ValidateCreate()).NotTo(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).NotTo(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(mhc.ValidateCreate()).To(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).To(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).NotTo(HaveOccurred()) } } } @@ -345,11 +358,15 @@ func TestMachineHealthCheckMaxUnhealthy(t *testing.T) { } if tt.expectErr { - g.Expect(mhc.ValidateCreate()).NotTo(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).NotTo(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(mhc.ValidateCreate()).To(Succeed()) - g.Expect(mhc.ValidateUpdate(mhc)).To(Succeed()) + _, err := mhc.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = mhc.ValidateUpdate(mhc) + g.Expect(err).NotTo(HaveOccurred()) } } } diff --git a/api/v1beta1/machineset_webhook.go b/api/v1beta1/machineset_webhook.go index 75dbfe9d34b8..cf5d76b7504a 100644 --- a/api/v1beta1/machineset_webhook.go +++ b/api/v1beta1/machineset_webhook.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" capilabels "sigs.k8s.io/cluster-api/internal/labels" "sigs.k8s.io/cluster-api/util/version" @@ -77,22 +78,22 @@ func (m *MachineSet) Default() { } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineSet) ValidateCreate() error { - return m.validate(nil) +func (m *MachineSet) ValidateCreate() (admission.Warnings, error) { + return nil, m.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineSet) ValidateUpdate(old runtime.Object) error { +func (m *MachineSet) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { oldMS, ok := old.(*MachineSet) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a MachineSet but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachineSet but got a %T", old)) } - return m.validate(oldMS) + return nil, m.validate(oldMS) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *MachineSet) ValidateDelete() error { - return nil +func (m *MachineSet) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (m *MachineSet) validate(old *MachineSet) error { diff --git a/api/v1beta1/machineset_webhook_test.go b/api/v1beta1/machineset_webhook_test.go index 43fd79a5f31b..01af9147a25e 100644 --- a/api/v1beta1/machineset_webhook_test.go +++ b/api/v1beta1/machineset_webhook_test.go @@ -104,12 +104,17 @@ func TestMachineSetLabelSelectorMatchValidation(t *testing.T) { }, }, } + if tt.expectErr { - g.Expect(ms.ValidateCreate()).NotTo(Succeed()) - g.Expect(ms.ValidateUpdate(ms)).NotTo(Succeed()) + _, err := ms.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = ms.ValidateUpdate(ms) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(ms.ValidateCreate()).To(Succeed()) - g.Expect(ms.ValidateUpdate(ms)).To(Succeed()) + _, err := ms.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = ms.ValidateUpdate(ms) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -152,10 +157,11 @@ func TestMachineSetClusterNameImmutable(t *testing.T) { }, } + _, err := newMS.ValidateUpdate(oldMS) if tt.expectErr { - g.Expect(newMS.ValidateUpdate(oldMS)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(newMS.ValidateUpdate(oldMS)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -209,11 +215,15 @@ func TestMachineSetVersionValidation(t *testing.T) { } if tt.expectErr { - g.Expect(md.ValidateCreate()).NotTo(Succeed()) - g.Expect(md.ValidateUpdate(md)).NotTo(Succeed()) + _, err := md.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = md.ValidateUpdate(md) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(md.ValidateCreate()).To(Succeed()) - g.Expect(md.ValidateUpdate(md)).To(Succeed()) + _, err := md.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = md.ValidateUpdate(md) + g.Expect(err).NotTo(HaveOccurred()) } }) } diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook.go b/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook.go index 32879de190f0..5ecf7b169692 100644 --- a/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook.go +++ b/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/cluster-api/feature" ) @@ -71,18 +72,18 @@ func DefaultKubeadmConfigSpec(r *KubeadmConfigSpec) { var _ webhook.Validator = &KubeadmConfig{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (c *KubeadmConfig) ValidateCreate() error { - return c.Spec.validate(c.Name) +func (c *KubeadmConfig) ValidateCreate() (admission.Warnings, error) { + return nil, c.Spec.validate(c.Name) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (c *KubeadmConfig) ValidateUpdate(_ runtime.Object) error { - return c.Spec.validate(c.Name) +func (c *KubeadmConfig) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { + return nil, c.Spec.validate(c.Name) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (c *KubeadmConfig) ValidateDelete() error { - return nil +func (c *KubeadmConfig) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (c *KubeadmConfigSpec) validate(name string) error { diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook_test.go b/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook_test.go index cd01a2940577..f89b87a6ac82 100644 --- a/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook_test.go +++ b/bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook_test.go @@ -462,12 +462,17 @@ func TestKubeadmConfigValidate(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.KubeadmBootstrapFormatIgnition, true)() } g := NewWithT(t) + if tt.expectErr { - g.Expect(tt.in.ValidateCreate()).NotTo(Succeed()) - g.Expect(tt.in.ValidateUpdate(nil)).NotTo(Succeed()) + _, err := tt.in.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = tt.in.ValidateUpdate(nil) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(tt.in.ValidateCreate()).To(Succeed()) - g.Expect(tt.in.ValidateUpdate(nil)).To(Succeed()) + _, err := tt.in.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = tt.in.ValidateUpdate(nil) + g.Expect(err).NotTo(HaveOccurred()) } }) } diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook.go b/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook.go index a1c581fa67b5..430923b14f81 100644 --- a/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook.go +++ b/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook.go @@ -22,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) func (r *KubeadmConfigTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { @@ -44,18 +45,18 @@ func (r *KubeadmConfigTemplate) Default() { var _ webhook.Validator = &KubeadmConfigTemplate{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *KubeadmConfigTemplate) ValidateCreate() error { - return r.Spec.validate(r.Name) +func (r *KubeadmConfigTemplate) ValidateCreate() (admission.Warnings, error) { + return nil, r.Spec.validate(r.Name) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *KubeadmConfigTemplate) ValidateUpdate(_ runtime.Object) error { - return r.Spec.validate(r.Name) +func (r *KubeadmConfigTemplate) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { + return nil, r.Spec.validate(r.Name) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *KubeadmConfigTemplate) ValidateDelete() error { - return nil +func (r *KubeadmConfigTemplate) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (r *KubeadmConfigTemplateSpec) validate(name string) error { diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook_test.go b/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook_test.go index c35a4b438f32..897858a10434 100644 --- a/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook_test.go +++ b/bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook_test.go @@ -68,8 +68,10 @@ func TestKubeadmConfigTemplateValidation(t *testing.T) { t.Run(name, func(t *testing.T) { g := NewWithT(t) - g.Expect(tt.in.ValidateCreate()).To(Succeed()) - g.Expect(tt.in.ValidateUpdate(nil)).To(Succeed()) + _, err := tt.in.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = tt.in.ValidateUpdate(nil) + g.Expect(err).NotTo(HaveOccurred()) }) } } diff --git a/bootstrap/kubeadm/config/manager/manager.yaml b/bootstrap/kubeadm/config/manager/manager.yaml index 7adfb709947b..d54386179159 100644 --- a/bootstrap/kubeadm/config/manager/manager.yaml +++ b/bootstrap/kubeadm/config/manager/manager.yaml @@ -21,7 +21,7 @@ spec: args: - "--leader-elect" - "--metrics-bind-addr=localhost:8080" - - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false},LazyRestmapper=${EXP_LAZY_RESTMAPPER:=false}" + - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false}" - "--bootstrap-token-ttl=${KUBEADM_BOOTSTRAP_TOKEN_TTL:=15m}" image: controller:latest name: manager diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go index b3477d10bf2f..45fe463f5d5b 100644 --- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go +++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go @@ -38,7 +38,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" @@ -118,19 +117,19 @@ func (r *KubeadmConfigReconciler) SetupWithManager(ctx context.Context, mgr ctrl For(&bootstrapv1.KubeadmConfig{}). WithOptions(options). Watches( - &source.Kind{Type: &clusterv1.Machine{}}, + &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(r.MachineToBootstrapMapFunc), ).WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)) if feature.Gates.Enabled(feature.MachinePool) { b = b.Watches( - &source.Kind{Type: &expv1.MachinePool{}}, + &expv1.MachinePool{}, handler.EnqueueRequestsFromMapFunc(r.MachinePoolToBootstrapMapFunc), ) } b = b.Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(r.ClusterToKubeadmConfigs), builder.WithPredicates( predicates.All(ctrl.LoggerFrom(ctx), @@ -808,7 +807,7 @@ func (r *KubeadmConfigReconciler) resolveSecretPasswordContent(ctx context.Conte // ClusterToKubeadmConfigs is a handler.ToRequestsFunc to be used to enqueue // requests for reconciliation of KubeadmConfigs. -func (r *KubeadmConfigReconciler) ClusterToKubeadmConfigs(o client.Object) []ctrl.Request { +func (r *KubeadmConfigReconciler) ClusterToKubeadmConfigs(ctx context.Context, o client.Object) []ctrl.Request { result := []ctrl.Request{} c, ok := o.(*clusterv1.Cluster) @@ -824,7 +823,7 @@ func (r *KubeadmConfigReconciler) ClusterToKubeadmConfigs(o client.Object) []ctr } machineList := &clusterv1.MachineList{} - if err := r.Client.List(context.TODO(), machineList, selectors...); err != nil { + if err := r.Client.List(ctx, machineList, selectors...); err != nil { return nil } @@ -838,7 +837,7 @@ func (r *KubeadmConfigReconciler) ClusterToKubeadmConfigs(o client.Object) []ctr if feature.Gates.Enabled(feature.MachinePool) { machinePoolList := &expv1.MachinePoolList{} - if err := r.Client.List(context.TODO(), machinePoolList, selectors...); err != nil { + if err := r.Client.List(ctx, machinePoolList, selectors...); err != nil { return nil } @@ -856,7 +855,7 @@ func (r *KubeadmConfigReconciler) ClusterToKubeadmConfigs(o client.Object) []ctr // MachineToBootstrapMapFunc is a handler.ToRequestsFunc to be used to enqueue // request for reconciliation of KubeadmConfig. -func (r *KubeadmConfigReconciler) MachineToBootstrapMapFunc(o client.Object) []ctrl.Request { +func (r *KubeadmConfigReconciler) MachineToBootstrapMapFunc(_ context.Context, o client.Object) []ctrl.Request { m, ok := o.(*clusterv1.Machine) if !ok { panic(fmt.Sprintf("Expected a Machine but got a %T", o)) @@ -872,7 +871,7 @@ func (r *KubeadmConfigReconciler) MachineToBootstrapMapFunc(o client.Object) []c // MachinePoolToBootstrapMapFunc is a handler.ToRequestsFunc to be used to enqueue // request for reconciliation of KubeadmConfig. -func (r *KubeadmConfigReconciler) MachinePoolToBootstrapMapFunc(o client.Object) []ctrl.Request { +func (r *KubeadmConfigReconciler) MachinePoolToBootstrapMapFunc(_ context.Context, o client.Object) []ctrl.Request { m, ok := o.(*expv1.MachinePool) if !ok { panic(fmt.Sprintf("Expected a MachinePool but got a %T", o)) diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller_test.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller_test.go index 4038c3a16f88..2aabce32c477 100644 --- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller_test.go +++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller_test.go @@ -80,7 +80,7 @@ func TestKubeadmConfigReconciler_MachineToBootstrapMapFuncReturn(t *testing.T) { } for i := 0; i < 3; i++ { o := machineObjs[i] - configs := reconciler.MachineToBootstrapMapFunc(o) + configs := reconciler.MachineToBootstrapMapFunc(ctx, o) if i == 1 { g.Expect(configs[0].Name).To(Equal(expectedConfigName)) } else { @@ -158,7 +158,7 @@ func TestKubeadmConfigReconciler_TestSecretOwnerReferenceReconciliation(t *testi secret, cluster, } - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -272,7 +272,7 @@ func TestKubeadmConfigReconciler_Reconcile_ReturnEarlyIfMachineHasDataSecretName machine, config, } - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -315,7 +315,7 @@ func TestKubeadmConfigReconciler_ReturnEarlyIfClusterInfraNotReady(t *testing.T) machine, config, } - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -450,7 +450,7 @@ func TestKubeadmConfigReconciler_Reconcile_RequeueJoiningNodesIfControlPlaneNotI t.Run(tc.name, func(t *testing.T) { g := NewWithT(t) - myclient := fake.NewClientBuilder().WithObjects(tc.objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(tc.objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -492,7 +492,7 @@ func TestKubeadmConfigReconciler_Reconcile_GenerateCloudConfigData(t *testing.T) } objects = append(objects, createSecrets(t, cluster, controlPlaneInitConfig)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -553,7 +553,7 @@ func TestKubeadmConfigReconciler_Reconcile_ErrorIfJoiningControlPlaneHasInvalidC controlPlaneJoinConfig, } objects = append(objects, createSecrets(t, cluster, controlPlaneInitConfig)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -597,7 +597,7 @@ func TestKubeadmConfigReconciler_Reconcile_RequeueIfControlPlaneIsMissingAPIEndp } objects = append(objects, createSecrets(t, cluster, controlPlaneInitConfig)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -675,7 +675,7 @@ func TestReconcileIfJoinCertificatesAvailableConditioninNodesAndControlPlaneIsRe config, } objects = append(objects, createSecrets(t, cluster, config)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, KubeadmInitLock: &myInitLocker{}, @@ -752,7 +752,7 @@ func TestReconcileIfJoinNodePoolsAndControlPlaneIsReady(t *testing.T) { config, } objects = append(objects, createSecrets(t, cluster, config)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, KubeadmInitLock: &myInitLocker{}, @@ -851,7 +851,7 @@ func TestBootstrapDataFormat(t *testing.T) { } objects = append(objects, createSecrets(t, cluster, config)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, @@ -932,7 +932,7 @@ func TestKubeadmConfigSecretCreatedStatusNotPatched(t *testing.T) { } objects = append(objects, createSecrets(t, cluster, initConfig)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, KubeadmInitLock: &myInitLocker{}, @@ -1009,7 +1009,7 @@ func TestBootstrapTokenTTLExtension(t *testing.T) { } objects = append(objects, createSecrets(t, cluster, initConfig)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}, &clusterv1.Machine{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, KubeadmInitLock: &myInitLocker{}, @@ -1210,7 +1210,7 @@ func TestBootstrapTokenRotationMachinePool(t *testing.T) { } objects = append(objects, createSecrets(t, cluster, initConfig)...) - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}, &expv1.MachinePool{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, KubeadmInitLock: &myInitLocker{}, @@ -1766,7 +1766,7 @@ func TestKubeadmConfigReconciler_ClusterToKubeadmConfigs(t *testing.T) { reconciler := &KubeadmConfigReconciler{ Client: fakeClient, } - configs := reconciler.ClusterToKubeadmConfigs(cluster) + configs := reconciler.ClusterToKubeadmConfigs(ctx, cluster) names := make([]string, 6) for i := range configs { names[i] = configs[i].Name @@ -1835,7 +1835,7 @@ func TestKubeadmConfigReconciler_Reconcile_ExactlyOneControlPlaneMachineInitiali controlPlaneInitMachineSecond, controlPlaneInitConfigSecond, } - myclient := fake.NewClientBuilder().WithObjects(objects...).Build() + myclient := fake.NewClientBuilder().WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build() k := &KubeadmConfigReconciler{ Client: myclient, KubeadmInitLock: &myInitLocker{}, diff --git a/bootstrap/kubeadm/main.go b/bootstrap/kubeadm/main.go index 9a0d26c92ddb..699f166b53e6 100644 --- a/bootstrap/kubeadm/main.go +++ b/bootstrap/kubeadm/main.go @@ -21,7 +21,6 @@ import ( "context" "flag" "fmt" - "net/http" _ "net/http/pprof" "os" "time" @@ -29,10 +28,8 @@ import ( // +kubebuilder:scaffold:imports "github.com/spf13/pflag" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection/resourcelock" cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/logs" @@ -40,9 +37,10 @@ import ( _ "k8s.io/component-base/logs/json/register" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/webhook" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1alpha3 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1alpha3" @@ -164,15 +162,6 @@ func main() { // klog.Background will automatically use the right logger. ctrl.SetLogger(klog.Background()) - if profilerAddress != "" { - setupLog.Info(fmt.Sprintf("Profiler listening for requests at %s", profilerAddress)) - go func() { - srv := http.Server{Addr: profilerAddress, ReadHeaderTimeout: 2 * time.Second} - if err := srv.ListenAndServe(); err != nil { - setupLog.Error(err, "problem running profiler server") - } - }() - } restConfig := ctrl.GetConfigOrDie() restConfig.QPS = restConfigQPS @@ -185,6 +174,11 @@ func main() { os.Exit(1) } + var watchNamespaces []string + if watchNamespace != "" { + watchNamespaces = []string{watchNamespace} + } + ctrlOptions := ctrl.Options{ Scheme: scheme, MetricsBindAddress: metricsBindAddr, @@ -194,22 +188,27 @@ func main() { RenewDeadline: &leaderElectionRenewDeadline, RetryPeriod: &leaderElectionRetryPeriod, LeaderElectionResourceLock: resourcelock.LeasesResourceLock, - Namespace: watchNamespace, - SyncPeriod: &syncPeriod, - ClientDisableCacheFor: []client.Object{ - &corev1.ConfigMap{}, - &corev1.Secret{}, + HealthProbeBindAddress: healthAddr, + PprofBindAddress: profilerAddress, + Cache: cache.Options{ + Namespaces: watchNamespaces, + SyncPeriod: &syncPeriod, }, - Port: webhookPort, - HealthProbeBindAddress: healthAddr, - CertDir: webhookCertDir, - TLSOpts: tlsOptionOverrides, - } - - if feature.Gates.Enabled(feature.LazyRestmapper) { - ctrlOptions.MapperProvider = func(c *rest.Config) (meta.RESTMapper, error) { - return apiutil.NewDynamicRESTMapper(c, apiutil.WithExperimentalLazyMapper) - } + Client: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: []client.Object{ + &corev1.ConfigMap{}, + &corev1.Secret{}, + }, + }, + }, + WebhookServer: webhook.NewServer( + webhook.Options{ + Port: webhookPort, + CertDir: webhookCertDir, + TLSOpts: tlsOptionOverrides, + }, + ), } mgr, err := ctrl.NewManager(restConfig, ctrlOptions) diff --git a/cmd/clusterctl/client/client_test.go b/cmd/clusterctl/client/client_test.go index b1374b805255..95a25c28690b 100644 --- a/cmd/clusterctl/client/client_test.go +++ b/cmd/clusterctl/client/client_test.go @@ -17,6 +17,7 @@ limitations under the License. package client import ( + "context" "fmt" "testing" "time" @@ -209,7 +210,7 @@ func newFakeCluster(kubeconfig cluster.Kubeconfig, configClient config.Client) * } fake.fakeProxy = test.NewFakeProxy() - pollImmediateWaiter := func(interval, timeout time.Duration, condition wait.ConditionFunc) error { + pollImmediateWaiter := func(ctx context.Context, interval, timeout time.Duration, condition wait.ConditionWithContextFunc) error { return nil } diff --git a/cmd/clusterctl/client/cluster/cert_manager.go b/cmd/clusterctl/client/cluster/cert_manager.go index dc1d3a91984b..954c401b9d95 100644 --- a/cmd/clusterctl/client/cluster/cert_manager.go +++ b/cmd/clusterctl/client/cluster/cert_manager.go @@ -526,7 +526,7 @@ func (cm *certManagerClient) deleteObj(obj unstructured.Unstructured) error { // cert-manager API group. // If retry is true, the createObj call will be retried if it fails. Otherwise, the // 'create' operations will only be attempted once. -func (cm *certManagerClient) waitForAPIReady(_ context.Context, retry bool) error { +func (cm *certManagerClient) waitForAPIReady(ctx context.Context, retry bool) error { log := logf.Log // Waits for the cert-manager to be available. if retry { @@ -544,7 +544,7 @@ func (cm *certManagerClient) waitForAPIReady(_ context.Context, retry bool) erro // Create the Kubernetes object. // This is wrapped with a retry as the cert-manager API may not be available // yet, so we need to keep retrying until it is. - if err := cm.pollImmediateWaiter(waitCertManagerInterval, cm.getWaitTimeout(), func() (bool, error) { + if err := cm.pollImmediateWaiter(ctx, waitCertManagerInterval, cm.getWaitTimeout(), func(ctx context.Context) (bool, error) { if err := cm.createObj(o); err != nil { // If retrying is disabled, return the error here. if !retry { diff --git a/cmd/clusterctl/client/cluster/cert_manager_test.go b/cmd/clusterctl/client/cluster/cert_manager_test.go index 480cbca885d5..1f530c5fcf4e 100644 --- a/cmd/clusterctl/client/cluster/cert_manager_test.go +++ b/cmd/clusterctl/client/cluster/cert_manager_test.go @@ -17,6 +17,7 @@ limitations under the License. package cluster import ( + "context" "fmt" "testing" "time" @@ -165,7 +166,7 @@ func Test_getManifestObjs(t *testing.T) { } func Test_GetTimeout(t *testing.T) { - pollImmediateWaiter := func(interval, timeout time.Duration, condition wait.ConditionFunc) error { + pollImmediateWaiter := func(ctx context.Context, interval, timeout time.Duration, condition wait.ConditionWithContextFunc) error { return nil } @@ -421,7 +422,7 @@ func Test_shouldUpgrade(t *testing.T) { g := NewWithT(t) proxy := test.NewFakeProxy() fakeConfigClient := newFakeConfig().WithCertManager("", tt.configVersion, "") - pollImmediateWaiter := func(interval, timeout time.Duration, condition wait.ConditionFunc) error { + pollImmediateWaiter := func(ctx context.Context, interval, timeout time.Duration, condition wait.ConditionWithContextFunc) error { return nil } cm := newCertManagerClient(fakeConfigClient, nil, proxy, pollImmediateWaiter) @@ -706,7 +707,7 @@ func Test_certManagerClient_PlanUpgrade(t *testing.T) { proxy := test.NewFakeProxy().WithObjs(tt.objs...) fakeConfigClient := newFakeConfig() - pollImmediateWaiter := func(interval, timeout time.Duration, condition wait.ConditionFunc) error { + pollImmediateWaiter := func(ctx context.Context, interval, timeout time.Duration, condition wait.ConditionWithContextFunc) error { return nil } cm := newCertManagerClient(fakeConfigClient, nil, proxy, pollImmediateWaiter) diff --git a/cmd/clusterctl/client/cluster/client.go b/cmd/clusterctl/client/cluster/client.go index bd34d912581b..5e3fc833df9b 100644 --- a/cmd/clusterctl/client/cluster/client.go +++ b/cmd/clusterctl/client/cluster/client.go @@ -89,7 +89,7 @@ type Client interface { } // PollImmediateWaiter tries a condition func until it returns true, an error, or the timeout is reached. -type PollImmediateWaiter func(interval, timeout time.Duration, condition wait.ConditionFunc) error +type PollImmediateWaiter func(ctx context.Context, interval, timeout time.Duration, condition wait.ConditionWithContextFunc) error // clusterClient implements Client. type clusterClient struct { @@ -214,7 +214,9 @@ func newClusterClient(kubeconfig Kubeconfig, configClient config.Client, options // if there is an injected PollImmediateWaiter, use it, otherwise use the default one if client.pollImmediateWaiter == nil { - client.pollImmediateWaiter = wait.PollImmediate + client.pollImmediateWaiter = func(ctx context.Context, interval, timeout time.Duration, condition wait.ConditionWithContextFunc) error { + return wait.PollUntilContextTimeout(ctx, interval, timeout, true, condition) + } } return client diff --git a/cmd/clusterctl/client/cluster/installer.go b/cmd/clusterctl/client/cluster/installer.go index 34010bc631f0..908c37ce747c 100644 --- a/cmd/clusterctl/client/cluster/installer.go +++ b/cmd/clusterctl/client/cluster/installer.go @@ -141,7 +141,7 @@ func waitManagerDeploymentsReady(opts InstallOptions, installQueue []repository. for _, obj := range components.Objs() { if util.IsDeploymentWithManager(obj) { if err := waitDeploymentReady(obj, opts.WaitProviderTimeout, proxy); err != nil { - return err + return errors.Wrapf(err, "deployment %q is not ready after %s", obj.GetName(), opts.WaitProviderTimeout) } } } @@ -150,7 +150,7 @@ func waitManagerDeploymentsReady(opts InstallOptions, installQueue []repository. } func waitDeploymentReady(deployment unstructured.Unstructured, timeout time.Duration, proxy Proxy) error { - return wait.Poll(100*time.Millisecond, timeout, func() (bool, error) { + return wait.PollUntilContextTimeout(context.TODO(), 100*time.Millisecond, timeout, false, func(ctx context.Context) (bool, error) { c, err := proxy.NewClient() if err != nil { return false, err @@ -160,7 +160,7 @@ func waitDeploymentReady(deployment unstructured.Unstructured, timeout time.Dura Name: deployment.GetName(), } dep := &appsv1.Deployment{} - if err := c.Get(context.TODO(), key, dep); err != nil { + if err := c.Get(ctx, key, dep); err != nil { return false, err } for _, c := range dep.Status.Conditions { diff --git a/cmd/clusterctl/client/cluster/internal/dryrun/client.go b/cmd/clusterctl/client/cluster/internal/dryrun/client.go index aa08f8e6d53b..f2ee99c4c869 100644 --- a/cmd/clusterctl/client/cluster/internal/dryrun/client.go +++ b/cmd/clusterctl/client/cluster/internal/dryrun/client.go @@ -30,6 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/client/fake" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/scheme" ) @@ -114,7 +115,7 @@ type ChangeSummary struct { // when the objects are not found in the internal object tracker. Typically the apiReader passed would be a reader client // to a real Kubernetes Cluster. func NewClient(apiReader client.Reader, objs []client.Object) *Client { - fakeClient := fake.NewClientBuilder().WithObjects(objs...).WithScheme(localScheme).Build() + fakeClient := fake.NewClientBuilder().WithObjects(objs...).WithStatusSubresource(&clusterv1.ClusterClass{}, &clusterv1.Cluster{}).WithScheme(localScheme).Build() return &Client{ fakeClient: fakeClient, apiReader: apiReader, @@ -308,6 +309,16 @@ func (c *Client) SubResource(subResource string) client.SubResourceClient { return c.fakeClient.SubResource(subResource) } +// GroupVersionKindFor returns the GroupVersionKind for the given object. +func (c *Client) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { + return c.fakeClient.GroupVersionKindFor(obj) +} + +// IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. +func (c *Client) IsObjectNamespaced(obj runtime.Object) (bool, error) { + return c.fakeClient.IsObjectNamespaced(obj) +} + // Changes generates a summary of all the changes observed from the creation of the dry run client // to when this function is called. func (c *Client) Changes(ctx context.Context) (*ChangeSummary, error) { diff --git a/cmd/clusterctl/client/cluster/inventory.go b/cmd/clusterctl/client/cluster/inventory.go index c71529c3ef4c..6f621bf43dc8 100644 --- a/cmd/clusterctl/client/cluster/inventory.go +++ b/cmd/clusterctl/client/cluster/inventory.go @@ -17,6 +17,7 @@ limitations under the License. package cluster import ( + "context" "fmt" "time" @@ -197,7 +198,7 @@ func (p *inventoryClient) EnsureCustomResourceDefinitions() error { // If the object is a CRDs, waits for it being Established. if apiextensionsv1.SchemeGroupVersion.WithKind("CustomResourceDefinition").GroupKind() == o.GroupVersionKind().GroupKind() { crdKey := client.ObjectKeyFromObject(&o) - if err := p.pollImmediateWaiter(waitInventoryCRDInterval, waitInventoryCRDTimeout, func() (bool, error) { + if err := p.pollImmediateWaiter(ctx, waitInventoryCRDInterval, waitInventoryCRDTimeout, func(ctx context.Context) (bool, error) { c, err := p.proxy.NewClient() if err != nil { return false, err diff --git a/cmd/clusterctl/client/cluster/inventory_test.go b/cmd/clusterctl/client/cluster/inventory_test.go index 92916358c2ba..cf2b89907ec8 100644 --- a/cmd/clusterctl/client/cluster/inventory_test.go +++ b/cmd/clusterctl/client/cluster/inventory_test.go @@ -17,6 +17,7 @@ limitations under the License. package cluster import ( + "context" "testing" "time" @@ -31,7 +32,7 @@ import ( "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test" ) -func fakePollImmediateWaiter(_, _ time.Duration, _ wait.ConditionFunc) error { +func fakePollImmediateWaiter(_ context.Context, _, _ time.Duration, _ wait.ConditionWithContextFunc) error { return nil } diff --git a/cmd/clusterctl/client/cluster/topology.go b/cmd/clusterctl/client/cluster/topology.go index 0242f1262627..a8d6f9d082f2 100644 --- a/cmd/clusterctl/client/cluster/topology.go +++ b/cmd/clusterctl/client/cluster/topology.go @@ -567,11 +567,11 @@ func (t *topologyClient) defaultAndValidateObjs(ctx context.Context, objs []*uns } } if oldObject != nil { - if err := validator.ValidateUpdate(ctx, oldObject, object); err != nil { + if _, err := validator.ValidateUpdate(ctx, oldObject, object); err != nil { return errors.Wrapf(err, "failed validation of %s %s/%s", obj.GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) } } else { - if err := validator.ValidateCreate(ctx, object); err != nil { + if _, err := validator.ValidateCreate(ctx, object); err != nil { return errors.Wrapf(err, "failed validation of %s %s/%s", obj.GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) } } diff --git a/cmd/clusterctl/client/init.go b/cmd/clusterctl/client/init.go index 9057b90d789c..20e30f0b9cdd 100644 --- a/cmd/clusterctl/client/init.go +++ b/cmd/clusterctl/client/init.go @@ -92,6 +92,12 @@ type InitOptions struct { func (c *clusterctlClient) Init(options InitOptions) ([]Components, error) { log := logf.Log + // Default WaitProviderTimeout as we cannot rely on defaulting in the CLI + // when clusterctl is used as a library. + if options.WaitProviderTimeout.Nanoseconds() == 0 { + options.WaitProviderTimeout = time.Duration(5*60) * time.Second + } + // gets access to the management cluster clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig}) if err != nil { diff --git a/cmd/clusterctl/client/repository/repository_github.go b/cmd/clusterctl/client/repository/repository_github.go index 71f66b83e75c..ff13bfdc2f40 100644 --- a/cmd/clusterctl/client/repository/repository_github.go +++ b/cmd/clusterctl/client/repository/repository_github.go @@ -290,10 +290,10 @@ func (g *gitHubRepository) getVersions() ([]string, error) { // NB. currently Github API does not support result ordering, so it not possible to limit results var allReleases []*github.RepositoryRelease var retryError error - _ = wait.PollImmediate(retryableOperationInterval, retryableOperationTimeout, func() (bool, error) { + _ = wait.PollUntilContextTimeout(context.TODO(), retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) { var listReleasesErr error // Get the first page of GitHub releases. - releases, response, listReleasesErr := client.Repositories.ListReleases(context.TODO(), g.owner, g.repository, &github.ListOptions{PerPage: githubListReleasesPerPageLimit}) + releases, response, listReleasesErr := client.Repositories.ListReleases(ctx, g.owner, g.repository, &github.ListOptions{PerPage: githubListReleasesPerPageLimit}) if listReleasesErr != nil { retryError = g.handleGithubErr(listReleasesErr, "failed to get the list of releases") // Return immediately if we are rate limited. @@ -308,7 +308,7 @@ func (g *gitHubRepository) getVersions() ([]string, error) { // pages in the response, which can be used to iterate through the pages. // https://github.com/google/go-github/blob/14bb610698fc2f9013cad5db79b2d5fe4d53e13c/github/github.go#L541-L551 for response.NextPage != 0 { - releases, response, listReleasesErr = client.Repositories.ListReleases(context.TODO(), g.owner, g.repository, &github.ListOptions{Page: response.NextPage, PerPage: githubListReleasesPerPageLimit}) + releases, response, listReleasesErr = client.Repositories.ListReleases(ctx, g.owner, g.repository, &github.ListOptions{Page: response.NextPage, PerPage: githubListReleasesPerPageLimit}) if listReleasesErr != nil { retryError = g.handleGithubErr(listReleasesErr, "failed to get the list of releases") // Return immediately if we are rate limited. @@ -353,9 +353,9 @@ func (g *gitHubRepository) getReleaseByTag(tag string) (*github.RepositoryReleas var release *github.RepositoryRelease var retryError error - _ = wait.PollImmediate(retryableOperationInterval, retryableOperationTimeout, func() (bool, error) { + _ = wait.PollUntilContextTimeout(context.TODO(), retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) { var getReleasesErr error - release, _, getReleasesErr = client.Repositories.GetReleaseByTag(context.TODO(), g.owner, g.repository, tag) + release, _, getReleasesErr = client.Repositories.GetReleaseByTag(ctx, g.owner, g.repository, tag) if getReleasesErr != nil { retryError = g.handleGithubErr(getReleasesErr, "failed to read release %q", tag) // Return immediately if not found @@ -405,7 +405,8 @@ func (g *gitHubRepository) downloadFilesFromRelease(release *github.RepositoryRe var reader io.ReadCloser var retryError error - _ = wait.PollImmediate(retryableOperationInterval, retryableOperationTimeout, func() (bool, error) { + var content []byte + _ = wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) { var redirect string var downloadReleaseError error reader, redirect, downloadReleaseError = client.Repositories.DownloadReleaseAsset(ctx, g.owner, g.repository, *assetID, http.DefaultClient) @@ -417,28 +418,29 @@ func (g *gitHubRepository) downloadFilesFromRelease(release *github.RepositoryRe } return false, nil } + defer reader.Close() + if redirect != "" { // NOTE: DownloadReleaseAsset should not return a redirect address when used with the DefaultClient. retryError = errors.New("unexpected redirect while downloading the release asset") return true, retryError } + // Read contents from the reader (redirect or not), and return. + var err error + content, err = io.ReadAll(reader) + if err != nil { + retryError = errors.Wrapf(err, "failed to read downloaded file %q from %q release", *release.TagName, fileName) + return false, nil + } + retryError = nil return true, nil }) - if reader != nil { - defer reader.Close() - } if retryError != nil { return nil, retryError } - // Read contents from the reader (redirect or not), and return. - content, err := io.ReadAll(reader) - if err != nil { - return nil, errors.Wrapf(err, "failed to read downloaded file %q from %q release", *release.TagName, fileName) - } - cacheFiles[cacheID] = content return content, nil } diff --git a/cmd/clusterctl/client/upgrade.go b/cmd/clusterctl/client/upgrade.go index c077aeaba34e..53e6c875267c 100644 --- a/cmd/clusterctl/client/upgrade.go +++ b/cmd/clusterctl/client/upgrade.go @@ -136,6 +136,12 @@ func (c *clusterctlClient) ApplyUpgrade(options ApplyUpgradeOptions) error { return errors.Errorf("current version of clusterctl could only upgrade to %s contract, requested %s", clusterv1.GroupVersion.Version, options.Contract) } + // Default WaitProviderTimeout as we cannot rely on defaulting in the CLI + // when clusterctl is used as a library. + if options.WaitProviderTimeout.Nanoseconds() == 0 { + options.WaitProviderTimeout = time.Duration(5*60) * time.Second + } + // Get the client for interacting with the management cluster. clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig}) if err != nil { diff --git a/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml b/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml index f7c6175f5e17..db0ffd3d15b8 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml @@ -290,10 +290,10 @@ spec: description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string name: - description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names' type: string uid: - description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids' type: string required: - apiVersion diff --git a/config/crd/bases/cluster.x-k8s.io_machinepools.yaml b/config/crd/bases/cluster.x-k8s.io_machinepools.yaml index 706383bbb9fa..2570928012ae 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinepools.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinepools.yaml @@ -231,10 +231,10 @@ spec: description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string name: - description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names' type: string uid: - description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids' type: string required: - apiVersion diff --git a/config/crd/bases/cluster.x-k8s.io_machinesets.yaml b/config/crd/bases/cluster.x-k8s.io_machinesets.yaml index a20f353095c7..d2c54cf8243c 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinesets.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinesets.yaml @@ -228,10 +228,10 @@ spec: description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string name: - description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names' type: string uid: - description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids' type: string required: - apiVersion diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 4d1b70b16622..5ac9b39670e8 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -22,7 +22,7 @@ spec: args: - "--leader-elect" - "--metrics-bind-addr=localhost:8080" - - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},ClusterResourceSet=${EXP_CLUSTER_RESOURCE_SET:=false},ClusterTopology=${CLUSTER_TOPOLOGY:=false},RuntimeSDK=${EXP_RUNTIME_SDK:=false},LazyRestmapper=${EXP_LAZY_RESTMAPPER:=false}" + - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},ClusterResourceSet=${EXP_CLUSTER_RESOURCE_SET:=false},ClusterTopology=${CLUSTER_TOPOLOGY:=false},RuntimeSDK=${EXP_RUNTIME_SDK:=false}" image: controller:latest name: manager env: diff --git a/controllers/external/tracker.go b/controllers/external/tracker.go index d482d89f4d27..650690b77f3c 100644 --- a/controllers/external/tracker.go +++ b/controllers/external/tracker.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" @@ -36,6 +37,7 @@ type ObjectTracker struct { m sync.Map Controller controller.Controller + Cache cache.Cache } // Watch uses the controller to issue a Watch only if the object hasn't been seen before. @@ -56,7 +58,7 @@ func (o *ObjectTracker) Watch(log logr.Logger, obj runtime.Object, handler handl log.Info("Adding watcher on external object", "groupVersionKind", gvk.String()) err := o.Controller.Watch( - &source.Kind{Type: u}, + source.Kind(o.Cache, u), handler, append(p, predicates.ResourceNotPaused(log))..., ) diff --git a/controllers/remote/cluster_cache_healthcheck_test.go b/controllers/remote/cluster_cache_healthcheck_test.go index 0ab126dea72b..6e10d6c38469 100644 --- a/controllers/remote/cluster_cache_healthcheck_test.go +++ b/controllers/remote/cluster_cache_healthcheck_test.go @@ -130,9 +130,13 @@ func TestClusterCacheHealthCheck(t *testing.T) { ctx, cancel := context.WithCancel(ctx) defer cancel() + httpClient, err := rest.HTTPClientFor(env.Config) + g.Expect(err).ToNot(HaveOccurred()) + go cct.healthCheckCluster(ctx, &healthCheckInput{ cluster: testClusterKey, cfg: env.Config, + httpClient: httpClient, interval: testPollInterval, requestTimeout: testPollTimeout, unhealthyThreshold: testUnhealthyThreshold, @@ -157,9 +161,13 @@ func TestClusterCacheHealthCheck(t *testing.T) { cct.deleteAccessor(ctx, testClusterKey) g.Expect(cct.clusterLock.TryLock(testClusterKey)).To(BeTrue()) startHealthCheck := time.Now() + + httpClient, err := rest.HTTPClientFor(env.Config) + g.Expect(err).ToNot(HaveOccurred()) cct.healthCheckCluster(ctx, &healthCheckInput{ cluster: testClusterKey, cfg: env.Config, + httpClient: httpClient, interval: testPollInterval, requestTimeout: testPollTimeout, unhealthyThreshold: testUnhealthyThreshold, @@ -180,10 +188,13 @@ func TestClusterCacheHealthCheck(t *testing.T) { ctx, cancel := context.WithCancel(ctx) defer cancel() + httpClient, err := rest.HTTPClientFor(env.Config) + g.Expect(err).ToNot(HaveOccurred()) go cct.healthCheckCluster(ctx, &healthCheckInput{ cluster: testClusterKey, cfg: env.Config, + httpClient: httpClient, interval: testPollInterval, requestTimeout: testPollTimeout, unhealthyThreshold: testUnhealthyThreshold, @@ -215,9 +226,12 @@ func TestClusterCacheHealthCheck(t *testing.T) { config := rest.CopyConfig(env.Config) config.Host = fmt.Sprintf("http://127.0.0.1:%d", l.Addr().(*net.TCPAddr).Port) + httpClient, err := rest.HTTPClientFor(env.Config) + g.Expect(err).ToNot(HaveOccurred()) go cct.healthCheckCluster(ctx, &healthCheckInput{ cluster: testClusterKey, cfg: config, + httpClient: httpClient, interval: testPollInterval, requestTimeout: testPollTimeout, unhealthyThreshold: testUnhealthyThreshold, diff --git a/controllers/remote/cluster_cache_tracker.go b/controllers/remote/cluster_cache_tracker.go index deb2c9eeae38..f506eed2603e 100644 --- a/controllers/remote/cluster_cache_tracker.go +++ b/controllers/remote/cluster_cache_tracker.go @@ -20,6 +20,7 @@ import ( "context" "crypto/rsa" "fmt" + "net/http" "os" "sync" "time" @@ -28,7 +29,6 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -48,7 +48,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" - "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/util/certs" "sigs.k8s.io/cluster-api/util/conditions" ) @@ -263,8 +262,8 @@ func (t *ClusterCacheTracker) newClusterAccessor(ctx context.Context, cluster cl return nil, errors.Wrapf(err, "error fetching REST client config for remote cluster %q", cluster.String()) } - // Create a client and a mapper for the cluster. - c, mapper, err := t.createClient(config, cluster) + // Create a client and a cache for the cluster. + c, cache, err := t.createClient(ctx, config, cluster, indexes) if err != nil { return nil, err } @@ -280,7 +279,7 @@ func (t *ClusterCacheTracker) newClusterAccessor(ctx context.Context, cluster cl if runningOnCluster { inClusterConfig, err := ctrl.GetConfig() if err != nil { - return nil, errors.Wrap(err, "error creating client for self-hosted cluster") + return nil, errors.Wrapf(err, "error creating client for self-hosted cluster %q", cluster.String()) } // Use CA and Host from in-cluster config. @@ -289,7 +288,7 @@ func (t *ClusterCacheTracker) newClusterAccessor(ctx context.Context, cluster cl config.Host = inClusterConfig.Host // Create a new client and overwrite the previously created client. - c, mapper, err = t.createClient(config, cluster) + c, cache, err = t.createClient(ctx, config, cluster, indexes) if err != nil { return nil, errors.Wrap(err, "error creating client for self-hosted cluster") } @@ -298,56 +297,6 @@ func (t *ClusterCacheTracker) newClusterAccessor(ctx context.Context, cluster cl log.Info(fmt.Sprintf("Creating cluster accessor for cluster %q with the regular apiserver endpoint %q", cluster.String(), config.Host)) } - // Create the cache for the remote cluster - cacheOptions := cache.Options{ - Scheme: t.scheme, - Mapper: mapper, - } - remoteCache, err := cache.New(config, cacheOptions) - if err != nil { - return nil, errors.Wrapf(err, "error creating cache for remote cluster %q", cluster.String()) - } - - cacheCtx, cacheCtxCancel := context.WithCancel(ctx) - - // We need to be able to stop the cache's shared informers, so wrap this in a stoppableCache. - cache := &stoppableCache{ - Cache: remoteCache, - cancelFunc: cacheCtxCancel, - } - - for _, index := range indexes { - if err := cache.IndexField(ctx, index.Object, index.Field, index.ExtractValue); err != nil { - return nil, fmt.Errorf("failed to index field %s: %w", index.Field, err) - } - } - - // Start the cache!!! - go cache.Start(cacheCtx) //nolint:errcheck - - // Wait until the cache is initially synced - cacheSyncCtx, cacheSyncCtxCancel := context.WithTimeout(ctx, initialCacheSyncTimeout) - defer cacheSyncCtxCancel() - if !cache.WaitForCacheSync(cacheSyncCtx) { - cache.Stop() - return nil, fmt.Errorf("failed waiting for cache for remote cluster %v to sync: %w", cluster, cacheCtx.Err()) - } - - // Start cluster healthcheck!!! - go t.healthCheckCluster(cacheCtx, &healthCheckInput{ - cluster: cluster, - cfg: config, - }) - - delegatingClient, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cache, - Client: c, - UncachedObjects: t.clientUncachedObjects, - }) - if err != nil { - return nil, err - } - // Generating a new private key to be used for generating temporary certificates to connect to // etcd on the target cluster. // NOTE: Generating a private key is an expensive operation, so we store it in the cluster accessor. @@ -359,7 +308,7 @@ func (t *ClusterCacheTracker) newClusterAccessor(ctx context.Context, cluster cl return &clusterAccessor{ cache: cache, config: config, - client: delegatingClient, + client: c, watches: sets.Set[string]{}, etcdClientCertificateKey: etcdKey, }, nil @@ -392,27 +341,78 @@ func (t *ClusterCacheTracker) runningOnWorkloadCluster(ctx context.Context, c cl } // createClient creates a client and a mapper based on a rest.Config. -func (t *ClusterCacheTracker) createClient(config *rest.Config, cluster client.ObjectKey) (client.Client, meta.RESTMapper, error) { - var mapper meta.RESTMapper - var err error +func (t *ClusterCacheTracker) createClient(ctx context.Context, config *rest.Config, cluster client.ObjectKey, indexes []Index) (client.Client, *stoppableCache, error) { + // Create a http client for the cluster. + httpClient, err := rest.HTTPClientFor(config) + if err != nil { + return nil, nil, errors.Wrapf(err, "error creating http client for remote cluster %q", cluster.String()) + } // Create a mapper for it - if !feature.Gates.Enabled(feature.LazyRestmapper) { - mapper, err = apiutil.NewDynamicRESTMapper(config) - } else { - mapper, err = apiutil.NewDynamicRESTMapper(config, apiutil.WithExperimentalLazyMapper) - } + mapper, err := apiutil.NewDynamicRESTMapper(config, httpClient) if err != nil { return nil, nil, errors.Wrapf(err, "error creating dynamic rest mapper for remote cluster %q", cluster.String()) } + // Create the cache for the remote cluster + cacheOptions := cache.Options{ + HTTPClient: httpClient, + Scheme: t.scheme, + Mapper: mapper, + } + remoteCache, err := cache.New(config, cacheOptions) + if err != nil { + return nil, nil, errors.Wrapf(err, "error creating cache for remote cluster %q", cluster.String()) + } + + cacheCtx, cacheCtxCancel := context.WithCancel(ctx) + + // We need to be able to stop the cache's shared informers, so wrap this in a stoppableCache. + cache := &stoppableCache{ + Cache: remoteCache, + cancelFunc: cacheCtxCancel, + } + + for _, index := range indexes { + if err := cache.IndexField(ctx, index.Object, index.Field, index.ExtractValue); err != nil { + return nil, nil, errors.Wrapf(err, "error adding index for field %q to cache for remote cluster %q", index.Field, cluster.String()) + } + } + // Create the client for the remote cluster - c, err := client.New(config, client.Options{Scheme: t.scheme, Mapper: mapper}) + c, err := client.New(config, client.Options{ + Scheme: t.scheme, + Mapper: mapper, + HTTPClient: httpClient, + Cache: &client.CacheOptions{ + Reader: cache, + DisableFor: t.clientUncachedObjects, + Unstructured: true, + }, + }) if err != nil { return nil, nil, errors.Wrapf(err, "error creating client for remote cluster %q", cluster.String()) } - return c, mapper, nil + // Start the cache!!! + go cache.Start(cacheCtx) //nolint:errcheck + + // Wait until the cache is initially synced + cacheSyncCtx, cacheSyncCtxCancel := context.WithTimeout(ctx, initialCacheSyncTimeout) + defer cacheSyncCtxCancel() + if !cache.WaitForCacheSync(cacheSyncCtx) { + cache.Stop() + return nil, nil, fmt.Errorf("failed waiting for cache for remote cluster %v to sync: %w", cluster, cacheCtx.Err()) + } + + // Start cluster healthcheck!!! + go t.healthCheckCluster(cacheCtx, &healthCheckInput{ + cluster: cluster, + cfg: config, + httpClient: httpClient, + }) + + return c, cache, nil } // deleteAccessor stops a clusterAccessor's cache and removes the clusterAccessor from the tracker. @@ -486,7 +486,7 @@ func (t *ClusterCacheTracker) Watch(ctx context.Context, input WatchInput) error } // Need to create the watch - if err := input.Watcher.Watch(source.NewKindWithCache(input.Kind, accessor.cache), input.EventHandler, input.Predicates...); err != nil { + if err := input.Watcher.Watch(source.Kind(accessor.cache, input.Kind), input.EventHandler, input.Predicates...); err != nil { return errors.Wrapf(err, "failed to add %s watch on cluster %s: failed to create watch", input.Kind, klog.KRef(input.Cluster.Namespace, input.Cluster.Name)) } @@ -498,6 +498,7 @@ func (t *ClusterCacheTracker) Watch(ctx context.Context, input WatchInput) error // healthCheckInput provides the input for the healthCheckCluster method. type healthCheckInput struct { cluster client.ObjectKey + httpClient *http.Client cfg *rest.Config interval time.Duration requestTimeout time.Duration @@ -535,9 +536,9 @@ func (t *ClusterCacheTracker) healthCheckCluster(ctx context.Context, in *health codec := runtime.NoopEncoder{Decoder: scheme.Codecs.UniversalDecoder()} cfg := rest.CopyConfig(in.cfg) cfg.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec}) - restClient, restClientErr := rest.UnversionedRESTClientFor(cfg) + restClient, restClientErr := rest.UnversionedRESTClientForConfigAndClient(cfg, in.httpClient) - runHealthCheckWithThreshold := func() (bool, error) { + runHealthCheckWithThreshold := func(ctx context.Context) (bool, error) { if restClientErr != nil { return false, restClientErr } @@ -593,12 +594,12 @@ func (t *ClusterCacheTracker) healthCheckCluster(ctx context.Context, in *health return false, nil } - err := wait.PollImmediateUntil(in.interval, runHealthCheckWithThreshold, ctx.Done()) + err := wait.PollUntilContextCancel(ctx, in.interval, true, runHealthCheckWithThreshold) // An error returned implies the health check has failed a sufficient number of // times for the cluster to be considered unhealthy // NB. we are ignoring ErrWaitTimeout because this error happens when the channel is close, that in this case // happens when the cache is explicitly stopped. - if err != nil && err != wait.ErrWaitTimeout { + if err != nil && !wait.Interrupted(err) { t.log.Error(err, "Error health checking cluster", "Cluster", klog.KRef(in.cluster.Namespace, in.cluster.Name)) t.deleteAccessor(ctx, in.cluster) } diff --git a/controllers/remote/cluster_cache_tracker_fake.go b/controllers/remote/cluster_cache_tracker_fake.go index 908eee6375ad..fd1c08a5e0e6 100644 --- a/controllers/remote/cluster_cache_tracker_fake.go +++ b/controllers/remote/cluster_cache_tracker_fake.go @@ -32,17 +32,9 @@ func NewTestClusterCacheTracker(log logr.Logger, cl client.Client, scheme *runti clusterAccessors: make(map[client.ObjectKey]*clusterAccessor), } - delegatingClient, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cl, - Client: cl, - }) - if err != nil { - panic(err) - } - testCacheTracker.clusterAccessors[objKey] = &clusterAccessor{ cache: nil, - client: delegatingClient, + client: cl, watches: sets.Set[string]{}.Insert(watchObjects...), } return testCacheTracker diff --git a/controllers/remote/cluster_cache_tracker_test.go b/controllers/remote/cluster_cache_tracker_test.go index 52f25346f755..91d530c27bf4 100644 --- a/controllers/remote/cluster_cache_tracker_test.go +++ b/controllers/remote/cluster_cache_tracker_test.go @@ -38,7 +38,7 @@ import ( "sigs.k8s.io/cluster-api/util/conditions" ) -func mapper(i client.Object) []reconcile.Request { +func mapper(_ context.Context, i client.Object) []reconcile.Request { return []reconcile.Request{ { NamespacedName: types.NamespacedName{ diff --git a/controllers/remote/cluster_test.go b/controllers/remote/cluster_test.go index 0fe782b62ec6..9c1622312e19 100644 --- a/controllers/remote/cluster_test.go +++ b/controllers/remote/cluster_test.go @@ -89,9 +89,14 @@ func TestNewClusterClient(t *testing.T) { gs := NewWithT(t) client := fake.NewClientBuilder().WithObjects(validSecret).Build() - _, err := NewClusterClient(ctx, "test-source", client, clusterWithValidKubeConfig) + c, err := NewClusterClient(ctx, "test-source", client, clusterWithValidKubeConfig) + gs.Expect(err).ToNot(HaveOccurred()) + // Since we do not have a remote server to connect to, we should expect to get // an error to that effect for the purpose of this test. + // Note: The error occurs here and not in `NewClusterClient` as with the lazy + // restmapper only the List call actually communicates with the server. + err = c.List(ctx, &corev1.NodeList{}) gs.Expect(err).To(MatchError(ContainSubstring("no such host"))) restConfig, err := RESTConfig(ctx, "test-source", client, clusterWithValidKubeConfig) diff --git a/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook.go b/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook.go index 50cce2e0456e..1120db1ce891 100644 --- a/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook.go +++ b/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook.go @@ -31,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" "sigs.k8s.io/cluster-api/internal/util/kubeadm" @@ -98,15 +99,15 @@ func defaultRolloutStrategy(rolloutStrategy *RolloutStrategy) *RolloutStrategy { } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (in *KubeadmControlPlane) ValidateCreate() error { +func (in *KubeadmControlPlane) ValidateCreate() (admission.Warnings, error) { spec := in.Spec allErrs := validateKubeadmControlPlaneSpec(spec, in.Namespace, field.NewPath("spec")) allErrs = append(allErrs, validateClusterConfiguration(spec.KubeadmConfigSpec.ClusterConfiguration, nil, field.NewPath("spec", "kubeadmConfigSpec", "clusterConfiguration"))...) allErrs = append(allErrs, spec.KubeadmConfigSpec.Validate(field.NewPath("spec", "kubeadmConfigSpec"))...) if len(allErrs) > 0 { - return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlane").GroupKind(), in.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlane").GroupKind(), in.Name, allErrs) } - return nil + return nil, nil } const ( @@ -134,7 +135,7 @@ const ( const minimumCertificatesExpiryDays = 7 // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (in *KubeadmControlPlane) ValidateUpdate(old runtime.Object) error { +func (in *KubeadmControlPlane) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // add a * to indicate everything beneath is ok. // For example, {"spec", "*"} will allow any path under "spec" to change. allowedPaths := [][]string{ @@ -196,25 +197,25 @@ func (in *KubeadmControlPlane) ValidateUpdate(old runtime.Object) error { prev, ok := old.(*KubeadmControlPlane) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expecting KubeadmControlPlane but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expecting KubeadmControlPlane but got a %T", old)) } originalJSON, err := json.Marshal(prev) if err != nil { - return apierrors.NewInternalError(err) + return nil, apierrors.NewInternalError(err) } modifiedJSON, err := json.Marshal(in) if err != nil { - return apierrors.NewInternalError(err) + return nil, apierrors.NewInternalError(err) } diff, err := jsonpatch.CreateMergePatch(originalJSON, modifiedJSON) if err != nil { - return apierrors.NewInternalError(err) + return nil, apierrors.NewInternalError(err) } jsonPatch := map[string]interface{}{} if err := json.Unmarshal(diff, &jsonPatch); err != nil { - return apierrors.NewInternalError(err) + return nil, apierrors.NewInternalError(err) } // Build a list of all paths that are trying to change diffpaths := paths([]string{}, jsonPatch) @@ -239,10 +240,10 @@ func (in *KubeadmControlPlane) ValidateUpdate(old runtime.Object) error { allErrs = append(allErrs, in.Spec.KubeadmConfigSpec.Validate(field.NewPath("spec", "kubeadmConfigSpec"))...) if len(allErrs) > 0 { - return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlane").GroupKind(), in.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlane").GroupKind(), in.Name, allErrs) } - return nil + return nil, nil } func validateKubeadmControlPlaneSpec(s KubeadmControlPlaneSpec, namespace string, pathPrefix *field.Path) field.ErrorList { @@ -659,6 +660,6 @@ func (in *KubeadmControlPlane) validateVersion(previousVersion string) (allErrs } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (in *KubeadmControlPlane) ValidateDelete() error { - return nil +func (in *KubeadmControlPlane) ValidateDelete() (admission.Warnings, error) { + return nil, nil } diff --git a/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook_test.go b/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook_test.go index 6ae774051a0f..86a4b62c1381 100644 --- a/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook_test.go +++ b/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook_test.go @@ -248,10 +248,11 @@ func TestKubeadmControlPlaneValidateCreate(t *testing.T) { g := NewWithT(t) + _, err := tt.kcp.ValidateCreate() if tt.expectErr { - g.Expect(tt.kcp.ValidateCreate()).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(tt.kcp.ValidateCreate()).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -1026,7 +1027,7 @@ func TestKubeadmControlPlaneValidateUpdate(t *testing.T) { g := NewWithT(t) - err := tt.kcp.ValidateUpdate(tt.before.DeepCopy()) + _, err := tt.kcp.ValidateUpdate(tt.before.DeepCopy()) if tt.expectErr { g.Expect(err).To(HaveOccurred()) } else { @@ -1231,7 +1232,7 @@ func TestKubeadmControlPlaneValidateUpdateAfterDefaulting(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) - err := tt.kcp.ValidateUpdate(tt.before.DeepCopy()) + _, err := tt.kcp.ValidateUpdate(tt.before.DeepCopy()) if tt.expectErr { g.Expect(err).To(HaveOccurred()) } else { diff --git a/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook.go b/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook.go index f08e8e3a8134..6ff3c43e36c8 100644 --- a/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook.go +++ b/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" "sigs.k8s.io/cluster-api/feature" @@ -54,11 +55,11 @@ func (r *KubeadmControlPlaneTemplate) Default() { var _ webhook.Validator = &KubeadmControlPlaneTemplate{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *KubeadmControlPlaneTemplate) ValidateCreate() error { +func (r *KubeadmControlPlaneTemplate) ValidateCreate() (admission.Warnings, error) { // NOTE: KubeadmControlPlaneTemplate is behind ClusterTopology feature gate flag; the web hook // must prevent creating new objects in case the feature flag is disabled. if !feature.Gates.Enabled(feature.ClusterTopology) { - return field.Forbidden( + return nil, field.Forbidden( field.NewPath("spec"), "can be set only if the ClusterTopology feature flag is enabled", ) @@ -69,17 +70,17 @@ func (r *KubeadmControlPlaneTemplate) ValidateCreate() error { allErrs = append(allErrs, validateClusterConfiguration(spec.KubeadmConfigSpec.ClusterConfiguration, nil, field.NewPath("spec", "template", "spec", "kubeadmConfigSpec", "clusterConfiguration"))...) allErrs = append(allErrs, spec.KubeadmConfigSpec.Validate(field.NewPath("spec", "template", "spec", "kubeadmConfigSpec"))...) if len(allErrs) > 0 { - return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlaneTemplate").GroupKind(), r.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlaneTemplate").GroupKind(), r.Name, allErrs) } - return nil + return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *KubeadmControlPlaneTemplate) ValidateUpdate(oldRaw runtime.Object) error { +func (r *KubeadmControlPlaneTemplate) ValidateUpdate(oldRaw runtime.Object) (admission.Warnings, error) { var allErrs field.ErrorList old, ok := oldRaw.(*KubeadmControlPlaneTemplate) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a KubeadmControlPlaneTemplate but got a %T", oldRaw)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a KubeadmControlPlaneTemplate but got a %T", oldRaw)) } if !reflect.DeepEqual(r.Spec.Template.Spec, old.Spec.Template.Spec) { @@ -89,14 +90,14 @@ func (r *KubeadmControlPlaneTemplate) ValidateUpdate(oldRaw runtime.Object) erro } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlaneTemplate").GroupKind(), r.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlaneTemplate").GroupKind(), r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *KubeadmControlPlaneTemplate) ValidateDelete() error { - return nil +func (r *KubeadmControlPlaneTemplate) ValidateDelete() (admission.Warnings, error) { + return nil, nil } // validateKubeadmControlPlaneTemplateResourceSpec is a copy of validateKubeadmControlPlaneSpec which diff --git a/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook_test.go b/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook_test.go index 64ebebe6a0e0..b6b5c4e7f616 100644 --- a/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook_test.go +++ b/controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook_test.go @@ -79,7 +79,8 @@ func TestKubeadmControlPlaneTemplateValidationFeatureGateEnabled(t *testing.T) { }, }, } - g.Expect(kcpTemplate.ValidateCreate()).To(Succeed()) + _, err := kcpTemplate.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) }) } @@ -103,6 +104,7 @@ func TestKubeadmControlPlaneTemplateValidationFeatureGateDisabled(t *testing.T) }, }, } - g.Expect(kcpTemplate.ValidateCreate()).NotTo(Succeed()) + _, err := kcpTemplate.ValidateCreate() + g.Expect(err).To(HaveOccurred()) }) } diff --git a/controlplane/kubeadm/config/manager/manager.yaml b/controlplane/kubeadm/config/manager/manager.yaml index 405f8c509c73..34e85f86e86d 100644 --- a/controlplane/kubeadm/config/manager/manager.yaml +++ b/controlplane/kubeadm/config/manager/manager.yaml @@ -21,7 +21,7 @@ spec: args: - "--leader-elect" - "--metrics-bind-addr=localhost:8080" - - "--feature-gates=ClusterTopology=${CLUSTER_TOPOLOGY:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false},LazyRestmapper=${EXP_LAZY_RESTMAPPER:=false}" + - "--feature-gates=ClusterTopology=${CLUSTER_TOPOLOGY:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false}" image: controller:latest name: manager env: diff --git a/controlplane/kubeadm/internal/controllers/controller.go b/controlplane/kubeadm/internal/controllers/controller.go index 882073d275fb..6d8bda6fc59d 100644 --- a/controlplane/kubeadm/internal/controllers/controller.go +++ b/controlplane/kubeadm/internal/controllers/controller.go @@ -36,7 +36,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" @@ -100,7 +99,7 @@ func (r *KubeadmControlPlaneReconciler) SetupWithManager(ctx context.Context, mg WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(r.ClusterToKubeadmControlPlane), builder.WithPredicates( predicates.All(ctrl.LoggerFrom(ctx), @@ -524,7 +523,7 @@ func (r *KubeadmControlPlaneReconciler) reconcileDelete(ctx context.Context, clu // ClusterToKubeadmControlPlane is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation // for KubeadmControlPlane based on updates to a Cluster. -func (r *KubeadmControlPlaneReconciler) ClusterToKubeadmControlPlane(o client.Object) []ctrl.Request { +func (r *KubeadmControlPlaneReconciler) ClusterToKubeadmControlPlane(_ context.Context, o client.Object) []ctrl.Request { c, ok := o.(*clusterv1.Cluster) if !ok { panic(fmt.Sprintf("Expected a Cluster but got a %T", o)) diff --git a/controlplane/kubeadm/internal/controllers/controller_test.go b/controlplane/kubeadm/internal/controllers/controller_test.go index 4d609592cda7..79e698e64625 100644 --- a/controlplane/kubeadm/internal/controllers/controller_test.go +++ b/controlplane/kubeadm/internal/controllers/controller_test.go @@ -91,7 +91,7 @@ func TestClusterToKubeadmControlPlane(t *testing.T) { recorder: record.NewFakeRecorder(32), } - got := r.ClusterToKubeadmControlPlane(cluster) + got := r.ClusterToKubeadmControlPlane(ctx, cluster) g.Expect(got).To(Equal(expectedResult)) } @@ -106,7 +106,7 @@ func TestClusterToKubeadmControlPlaneNoControlPlane(t *testing.T) { recorder: record.NewFakeRecorder(32), } - got := r.ClusterToKubeadmControlPlane(cluster) + got := r.ClusterToKubeadmControlPlane(ctx, cluster) g.Expect(got).To(BeNil()) } @@ -129,7 +129,7 @@ func TestClusterToKubeadmControlPlaneOtherControlPlane(t *testing.T) { recorder: record.NewFakeRecorder(32), } - got := r.ClusterToKubeadmControlPlane(cluster) + got := r.ClusterToKubeadmControlPlane(ctx, cluster) g.Expect(got).To(BeNil()) } @@ -246,7 +246,8 @@ func TestReconcileNoClusterOwnerRef(t *testing.T) { }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) fakeClient := newFakeClient(kcp.DeepCopy()) r := &KubeadmControlPlaneReconciler{ @@ -322,7 +323,8 @@ func TestReconcileNoCluster(t *testing.T) { }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) fakeClient := newFakeClient(kcp.DeepCopy()) r := &KubeadmControlPlaneReconciler{ @@ -330,7 +332,7 @@ func TestReconcileNoCluster(t *testing.T) { recorder: record.NewFakeRecorder(32), } - _, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(kcp)}) + _, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(kcp)}) g.Expect(err).To(HaveOccurred()) machineList := &clusterv1.MachineList{} @@ -371,14 +373,15 @@ func TestReconcilePaused(t *testing.T) { }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) fakeClient := newFakeClient(kcp.DeepCopy(), cluster.DeepCopy()) r := &KubeadmControlPlaneReconciler{ Client: fakeClient, recorder: record.NewFakeRecorder(32), } - _, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(kcp)}) + _, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(kcp)}) g.Expect(err).NotTo(HaveOccurred()) machineList := &clusterv1.MachineList{} @@ -424,7 +427,8 @@ func TestReconcileClusterNoEndpoints(t *testing.T) { }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) fakeClient := newFakeClient(kcp.DeepCopy(), cluster.DeepCopy()) r := &KubeadmControlPlaneReconciler{ @@ -633,7 +637,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) { }) t.Run("Deleted KubeadmControlPlanes don't adopt machines", func(t *testing.T) { - // Usually we won't get into the inner reconcile with a deleted control plane, but it's possible when deleting with "oprhanDependents": + // Usually we won't get into the inner reconcile with a deleted control plane, but it's possible when deleting with "orphanDependents": // 1. The deletion timestamp is set in the API server, but our cache has not yet updated // 2. The garbage collector removes our ownership reference from a Machine, triggering a re-reconcile (or we get unlucky with the periodic reconciliation) // 3. We get into the inner reconcile function and re-adopt the Machine @@ -648,6 +652,9 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) { now := metav1.Now() kcp.DeletionTimestamp = &now + // We also have to set a finalizer as fake client doesn't accept objects + // with a deletionTimestamp without a finalizer. + kcp.Finalizers = []string{"block-deletion"} fmc := &fakeManagementCluster{ Machines: collections.Machines{}, @@ -2165,7 +2172,7 @@ func TestKubeadmControlPlaneReconciler_reconcileDelete(t *testing.T) { func newFakeClient(initObjs ...client.Object) client.Client { return &fakeClient{ startTime: time.Now(), - Client: fake.NewClientBuilder().WithObjects(initObjs...).Build(), + Client: fake.NewClientBuilder().WithObjects(initObjs...).WithStatusSubresource(&controlplanev1.KubeadmControlPlane{}).Build(), } } diff --git a/controlplane/kubeadm/internal/controllers/status_test.go b/controlplane/kubeadm/internal/controllers/status_test.go index cf2e1c2a7e8a..6dd67b466802 100644 --- a/controlplane/kubeadm/internal/controllers/status_test.go +++ b/controlplane/kubeadm/internal/controllers/status_test.go @@ -66,7 +66,8 @@ func TestKubeadmControlPlaneReconciler_updateStatusNoMachines(t *testing.T) { }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) fakeClient := newFakeClient(kcp.DeepCopy(), cluster.DeepCopy()) log.SetLogger(klogr.New()) @@ -122,7 +123,8 @@ func TestKubeadmControlPlaneReconciler_updateStatusAllMachinesNotReady(t *testin }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) machines := map[string]*clusterv1.Machine{} objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy()} @@ -187,7 +189,8 @@ func TestKubeadmControlPlaneReconciler_updateStatusAllMachinesReady(t *testing.T }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy(), kubeadmConfigMap()} machines := map[string]*clusterv1.Machine{} @@ -260,7 +263,8 @@ func TestKubeadmControlPlaneReconciler_updateStatusMachinesReadyMixed(t *testing }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) machines := map[string]*clusterv1.Machine{} objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy()} for i := 0; i < 4; i++ { @@ -333,7 +337,8 @@ func TestKubeadmControlPlaneReconciler_machinesCreatedIsIsTrueEvenWhenTheNodesAr }, } kcp.Default() - g.Expect(kcp.ValidateCreate()).To(Succeed()) + _, err := kcp.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) machines := map[string]*clusterv1.Machine{} objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy()} // Create the desired number of machines diff --git a/controlplane/kubeadm/internal/webhooks/scale.go b/controlplane/kubeadm/internal/webhooks/scale.go index 506b398afaff..6ae6562873f0 100644 --- a/controlplane/kubeadm/internal/webhooks/scale.go +++ b/controlplane/kubeadm/internal/webhooks/scale.go @@ -32,6 +32,8 @@ import ( ) func (v *ScaleValidator) SetupWebhookWithManager(mgr ctrl.Manager) error { + v.decoder = admission.NewDecoder(mgr.GetScheme()) + mgr.GetWebhookServer().Register("/validate-scale-controlplane-cluster-x-k8s-io-v1beta1-kubeadmcontrolplane", &webhook.Admission{ Handler: v, }) @@ -80,11 +82,3 @@ func (v *ScaleValidator) Handle(ctx context.Context, req admission.Request) admi return admission.Allowed("") } - -// InjectDecoder injects the decoder. -// ScaleValidator implements admission.DecoderInjector. -// A decoder will be automatically injected. -func (v *ScaleValidator) InjectDecoder(d *admission.Decoder) error { - v.decoder = d - return nil -} diff --git a/controlplane/kubeadm/internal/webhooks/scale_test.go b/controlplane/kubeadm/internal/webhooks/scale_test.go index f074dcf20a3c..6d35c1402543 100644 --- a/controlplane/kubeadm/internal/webhooks/scale_test.go +++ b/controlplane/kubeadm/internal/webhooks/scale_test.go @@ -136,12 +136,12 @@ func TestKubeadmControlPlaneValidateScale(t *testing.T) { name string admissionRequest admission.Request expectRespAllowed bool - expectRespReason string + expectRespMessage string }{ { name: "should return error when trying to scale to zero", expectRespAllowed: false, - expectRespReason: "replicas cannot be 0", + expectRespMessage: "replicas cannot be 0", admissionRequest: admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{ UID: uuid.NewUUID(), Kind: metav1.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}, @@ -152,7 +152,7 @@ func TestKubeadmControlPlaneValidateScale(t *testing.T) { { name: "should return error when trying to scale to even number of replicas with managed etcd", expectRespAllowed: false, - expectRespReason: "replicas cannot be an even number when etcd is stacked", + expectRespMessage: "replicas cannot be an even number when etcd is stacked", admissionRequest: admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{ UID: uuid.NewUUID(), Kind: metav1.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}, @@ -163,7 +163,7 @@ func TestKubeadmControlPlaneValidateScale(t *testing.T) { { name: "should allow odd number of replicas with managed etcd", expectRespAllowed: true, - expectRespReason: "", + expectRespMessage: "", admissionRequest: admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{ UID: uuid.NewUUID(), Kind: metav1.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}, @@ -174,7 +174,7 @@ func TestKubeadmControlPlaneValidateScale(t *testing.T) { { name: "should allow even number of replicas with external etcd", expectRespAllowed: true, - expectRespReason: "", + expectRespMessage: "", admissionRequest: admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{ UID: uuid.NewUUID(), Kind: metav1.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}, @@ -185,7 +185,7 @@ func TestKubeadmControlPlaneValidateScale(t *testing.T) { { name: "should allow odd number of replicas with external etcd", expectRespAllowed: true, - expectRespReason: "", + expectRespMessage: "", admissionRequest: admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{ UID: uuid.NewUUID(), Kind: metav1.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "Scale"}, @@ -198,18 +198,17 @@ func TestKubeadmControlPlaneValidateScale(t *testing.T) { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) - decoder, _ := admission.NewDecoder(scheme) fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(kcpManagedEtcd, kcpExternalEtcd).Build() // Create the webhook and add the fakeClient as its client. scaleHandler := ScaleValidator{ Client: fakeClient, - decoder: decoder, + decoder: admission.NewDecoder(scheme), } resp := scaleHandler.Handle(context.Background(), tt.admissionRequest) g.Expect(resp.Allowed).Should(Equal(tt.expectRespAllowed)) - g.Expect(string(resp.Result.Reason)).Should(Equal(tt.expectRespReason)) + g.Expect(resp.Result.Message).Should(Equal(tt.expectRespMessage)) }) } } diff --git a/controlplane/kubeadm/main.go b/controlplane/kubeadm/main.go index 1dd0599e22c0..a0807f625724 100644 --- a/controlplane/kubeadm/main.go +++ b/controlplane/kubeadm/main.go @@ -21,7 +21,6 @@ import ( "context" "flag" "fmt" - "net/http" _ "net/http/pprof" "os" "time" @@ -31,10 +30,8 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection/resourcelock" cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/logs" @@ -42,9 +39,10 @@ import ( _ "k8s.io/component-base/logs/json/register" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/webhook" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" @@ -173,16 +171,6 @@ func main() { // klog.Background will automatically use the right logger. ctrl.SetLogger(klog.Background()) - if profilerAddress != "" { - setupLog.Info(fmt.Sprintf("Profiler listening for requests at %s", profilerAddress)) - go func() { - srv := http.Server{Addr: profilerAddress, ReadHeaderTimeout: 2 * time.Second} - if err := srv.ListenAndServe(); err != nil { - setupLog.Error(err, "problem running profiler server") - } - }() - } - restConfig := ctrl.GetConfigOrDie() restConfig.QPS = restConfigQPS restConfig.Burst = restConfigBurst @@ -194,6 +182,11 @@ func main() { os.Exit(1) } + var watchNamespaces []string + if watchNamespace != "" { + watchNamespaces = []string{watchNamespace} + } + ctrlOptions := ctrl.Options{ Scheme: scheme, MetricsBindAddress: metricsBindAddr, @@ -203,22 +196,27 @@ func main() { RenewDeadline: &leaderElectionRenewDeadline, RetryPeriod: &leaderElectionRetryPeriod, LeaderElectionResourceLock: resourcelock.LeasesResourceLock, - Namespace: watchNamespace, - SyncPeriod: &syncPeriod, - ClientDisableCacheFor: []client.Object{ - &corev1.ConfigMap{}, - &corev1.Secret{}, + HealthProbeBindAddress: healthAddr, + PprofBindAddress: profilerAddress, + Cache: cache.Options{ + Namespaces: watchNamespaces, + SyncPeriod: &syncPeriod, }, - Port: webhookPort, - HealthProbeBindAddress: healthAddr, - CertDir: webhookCertDir, - TLSOpts: tlsOptionOverrides, - } - - if feature.Gates.Enabled(feature.LazyRestmapper) { - ctrlOptions.MapperProvider = func(c *rest.Config) (meta.RESTMapper, error) { - return apiutil.NewDynamicRESTMapper(c, apiutil.WithExperimentalLazyMapper) - } + Client: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: []client.Object{ + &corev1.ConfigMap{}, + &corev1.Secret{}, + }, + }, + }, + WebhookServer: webhook.NewServer( + webhook.Options{ + Port: webhookPort, + CertDir: webhookCertDir, + TLSOpts: tlsOptionOverrides, + }, + ), } mgr, err := ctrl.NewManager(restConfig, ctrlOptions) diff --git a/docs/book/src/developer/providers/migrations/v1.4-to-v1.5.md b/docs/book/src/developer/providers/migrations/v1.4-to-v1.5.md index 8f2e8602d543..03bb08efcee1 100644 --- a/docs/book/src/developer/providers/migrations/v1.4-to-v1.5.md +++ b/docs/book/src/developer/providers/migrations/v1.4-to-v1.5.md @@ -3,7 +3,7 @@ This document provides an overview over relevant changes between Cluster API v1.4 and v1.5 for maintainers of providers and consumers of our Go API. -## Minimum Go version +## Go version - The Go version used by Cluster API is Go 1.20.x @@ -12,6 +12,8 @@ maintainers of providers and consumers of our Go API. **Note**: Only the most relevant dependencies are listed, `k8s.io/` and `ginkgo`/`gomega` dependencies in Cluster API are kept in sync with the versions used by `sigs.k8s.io/controller-runtime`. - sigs.k8s.io/kind: v0.17.x => v0.19.x +- sigs.k8s.io/controller-runtime: v0.14.x => v0.15.x +- sigs.k8s.io/controller-tools: v0.11.x => v0.12.x ## Changes by Kind @@ -22,6 +24,7 @@ maintainers of providers and consumers of our Go API. ### Removals - API version `v1alpha3` is not served in v1.5 (users can enable it manually in case they are lagging behind with deprecation cycles). Important: `v1alpha3` will be completely removed in 1.6. +- The lazy restmapper feature gate was removed in controller-runtime and lazy restmapper is now the default restmapper. Accordingly the `EXP_LAZY_RESTMAPPER` feature gate was removed in Cluster API. ### API Changes @@ -36,3 +39,22 @@ maintainers of providers and consumers of our Go API. ### Suggested changes for providers - + +## Notes about the controller-runtime bump + +This section shares our learnings of bumping controller-runtime to v0.15 in core Cluster API. It highlights the most relevant changes and pitfalls +for Cluster API providers. For the full list of changes please see the [controller-runtime release notes](https://github.com/kubernetes-sigs/controller-runtime/releases/tag/v0.15.0). + +* Webhooks can now also return warnings, this requires adding an additional `admission.Warnings` return parameter to all webhooks. +* Manager options have been refactored and old fields have been deprecated. +* Manager now has a builtin profiler server which can be enabled via `Options.PprofBindAddress`, this allows us to remove our profiler server. +* Controller builder has been refactored, this requires small changes to our controller setup code. +* The EventHandler interface has been modified to also take a context, which affects our mapping functions (e.g. `ClusterToInfrastructureMapFunc`). +* Controller-runtime now uses a lazy restmapper per default, i.e. API groups and resources are only fetched when they are actually used. + This should drastically reduce the amount of API calls in clusters with a lot of CRDs. +* Some wait utils in `k8s.io/apimachinery/pkg/util/wait` have been deprecated. The migration is relatively straightforward except that passing in `0` + as a timeout in `wait.PollUntilContextTimeout` is treated as a timeout with 0 seconds, in `wait.PollImmediateWithContext` it is interpreted as infinity. +* The fake client has been improved to handle status properly. In tests that write the CRD status, the CRDs should be added to the fake client via `WithStatusSubresource`. +* Ensure that the e2e test suite is setting a logger (e.g. via `ctrl.SetLogger(klog.Background())` in `TestE2E`. Otherwise logs are not visible and controller-runtime will print a warning. + +For reference, please see the [Bump to CR v0.15 PR](https://github.com/kubernetes-sigs/cluster-api/pull/8007) in core Cluster API. diff --git a/docs/book/src/developer/testing.md b/docs/book/src/developer/testing.md index 4617d06cdf49..5cbd1fe58125 100644 --- a/docs/book/src/developer/testing.md +++ b/docs/book/src/developer/testing.md @@ -267,7 +267,6 @@ kustomize_substitutions: EXP_CLUSTER_RESOURCE_SET: "true" EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true" EXP_RUNTIME_SDK: "true" - EXP_LAZY_RESTMAPPER: "true" ``` diff --git a/docs/book/src/developer/tilt.md b/docs/book/src/developer/tilt.md index 71ce088d26af..50be14bbd10b 100644 --- a/docs/book/src/developer/tilt.md +++ b/docs/book/src/developer/tilt.md @@ -110,7 +110,6 @@ kustomize_substitutions: EXP_CLUSTER_RESOURCE_SET: "true" EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true" EXP_RUNTIME_SDK: "true" - EXP_LAZY_RESTMAPPER: "true" ``` {{#tabs name:"tab-tilt-kustomize-substitution" tabs:"AWS,Azure,DigitalOcean,GCP,vSphere"}} diff --git a/docs/book/src/tasks/experimental-features/experimental-features.md b/docs/book/src/tasks/experimental-features/experimental-features.md index cacd21d96ba0..a03012fc2153 100644 --- a/docs/book/src/tasks/experimental-features/experimental-features.md +++ b/docs/book/src/tasks/experimental-features/experimental-features.md @@ -34,7 +34,6 @@ variables: EXP_MACHINE_POOL: "true" CLUSTER_TOPOLOGY: "true" EXP_RUNTIME_SDK: "true" - EXP_LAZY_RESTMAPPER: "true" ``` Another way is to set them as environmental variables before running e2e tests. @@ -49,7 +48,6 @@ kustomize_substitutions: EXP_MACHINE_POOL: 'true' CLUSTER_TOPOLOGY: 'true' EXP_RUNTIME_SDK: 'true' - EXP_LAZY_RESTMAPPER: 'true' ``` For more details on setting up a development environment with `tilt`, see [Developing Cluster API with Tilt](../../developer/tilt.md) @@ -65,7 +63,7 @@ kubectl edit -n capi-system deployment.apps/capi-controller-manager // Enable/disable available features by modifying Args below. Args: --leader-elect - --feature-gates=MachinePool=true,ClusterResourceSet=true,LazyRestmapper=true + --feature-gates=MachinePool=true,ClusterResourceSet=true ``` Similarly, to **validate** if a particular feature is enabled, see cluster-api-provider deployment arguments by: diff --git a/exp/addons/api/v1beta1/clusterresourceset_webhook.go b/exp/addons/api/v1beta1/clusterresourceset_webhook.go index 35ad6c661f5f..61f8f6dc5c02 100644 --- a/exp/addons/api/v1beta1/clusterresourceset_webhook.go +++ b/exp/addons/api/v1beta1/clusterresourceset_webhook.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/cluster-api/feature" ) @@ -51,22 +52,22 @@ func (m *ClusterResourceSet) Default() { } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *ClusterResourceSet) ValidateCreate() error { - return m.validate(nil) +func (m *ClusterResourceSet) ValidateCreate() (admission.Warnings, error) { + return nil, m.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *ClusterResourceSet) ValidateUpdate(old runtime.Object) error { +func (m *ClusterResourceSet) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { oldCRS, ok := old.(*ClusterResourceSet) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", old)) } - return m.validate(oldCRS) + return nil, m.validate(oldCRS) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *ClusterResourceSet) ValidateDelete() error { - return nil +func (m *ClusterResourceSet) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (m *ClusterResourceSet) validate(old *ClusterResourceSet) error { diff --git a/exp/addons/api/v1beta1/clusterresourceset_webhook_test.go b/exp/addons/api/v1beta1/clusterresourceset_webhook_test.go index c307af543f6f..77f0fbcd5a53 100644 --- a/exp/addons/api/v1beta1/clusterresourceset_webhook_test.go +++ b/exp/addons/api/v1beta1/clusterresourceset_webhook_test.go @@ -67,11 +67,15 @@ func TestClusterResourceSetLabelSelectorAsSelectorValidation(t *testing.T) { }, } if tt.expectErr { - g.Expect(clusterResourceSet.ValidateCreate()).NotTo(Succeed()) - g.Expect(clusterResourceSet.ValidateUpdate(clusterResourceSet)).NotTo(Succeed()) + _, err := clusterResourceSet.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = clusterResourceSet.ValidateUpdate(clusterResourceSet) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(clusterResourceSet.ValidateCreate()).To(Succeed()) - g.Expect(clusterResourceSet.ValidateUpdate(clusterResourceSet)).To(Succeed()) + _, err := clusterResourceSet.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = clusterResourceSet.ValidateUpdate(clusterResourceSet) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -124,11 +128,12 @@ func TestClusterResourceSetStrategyImmutable(t *testing.T) { }, } + _, err := newClusterResourceSet.ValidateUpdate(oldClusterResourceSet) if tt.expectErr { - g.Expect(newClusterResourceSet.ValidateUpdate(oldClusterResourceSet)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) return } - g.Expect(newClusterResourceSet.ValidateUpdate(oldClusterResourceSet)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) }) } } @@ -174,11 +179,12 @@ func TestClusterResourceSetClusterSelectorImmutable(t *testing.T) { }, } + _, err := newClusterResourceSet.ValidateUpdate(oldClusterResourceSet) if tt.expectErr { - g.Expect(newClusterResourceSet.ValidateUpdate(oldClusterResourceSet)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) return } - g.Expect(newClusterResourceSet.ValidateUpdate(oldClusterResourceSet)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) }) } } diff --git a/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook.go b/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook.go index 91a5b12c49f8..1f51795173b5 100644 --- a/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook.go +++ b/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/cluster-api/feature" ) @@ -39,22 +40,22 @@ func (c *ClusterResourceSetBinding) SetupWebhookWithManager(mgr ctrl.Manager) er var _ webhook.Validator = &ClusterResourceSetBinding{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (c *ClusterResourceSetBinding) ValidateCreate() error { - return c.validate(nil) +func (c *ClusterResourceSetBinding) ValidateCreate() (admission.Warnings, error) { + return nil, c.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (c *ClusterResourceSetBinding) ValidateUpdate(old runtime.Object) error { +func (c *ClusterResourceSetBinding) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { oldBinding, ok := old.(*ClusterResourceSetBinding) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSetBinding but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSetBinding but got a %T", old)) } - return c.validate(oldBinding) + return nil, c.validate(oldBinding) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (c *ClusterResourceSetBinding) ValidateDelete() error { - return nil +func (c *ClusterResourceSetBinding) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func (c *ClusterResourceSetBinding) validate(old *ClusterResourceSetBinding) error { diff --git a/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook_test.go b/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook_test.go index 0530a6183edc..eacaf608e05a 100644 --- a/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook_test.go +++ b/exp/addons/api/v1beta1/clusterresourcesetbinding_webhook_test.go @@ -77,13 +77,15 @@ func TestClusterResourceSetBindingClusterNameImmutable(t *testing.T) { }, } + _, err := newClusterResourceSetBinding.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) if tt.expectErr { - g.Expect(newClusterResourceSetBinding.ValidateCreate()).To(Succeed()) - g.Expect(newClusterResourceSetBinding.ValidateUpdate(oldClusterResourceSetBinding)).NotTo(Succeed()) - return + _, err = newClusterResourceSetBinding.ValidateUpdate(oldClusterResourceSetBinding) + g.Expect(err).To(HaveOccurred()) + } else { + _, err = newClusterResourceSetBinding.ValidateUpdate(oldClusterResourceSetBinding) + g.Expect(err).NotTo(HaveOccurred()) } - g.Expect(newClusterResourceSetBinding.ValidateCreate()).To(Succeed()) - g.Expect(newClusterResourceSetBinding.ValidateUpdate(oldClusterResourceSetBinding)).To(Succeed()) }) } } diff --git a/exp/addons/internal/controllers/clusterresourceset_controller.go b/exp/addons/internal/controllers/clusterresourceset_controller.go index fac5504473f7..46c4e02c44d2 100644 --- a/exp/addons/internal/controllers/clusterresourceset_controller.go +++ b/exp/addons/internal/controllers/clusterresourceset_controller.go @@ -37,7 +37,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/remote" @@ -70,21 +69,19 @@ func (r *ClusterResourceSetReconciler) SetupWithManager(ctx context.Context, mgr err := ctrl.NewControllerManagedBy(mgr). For(&addonsv1.ClusterResourceSet{}). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(r.clusterToClusterResourceSet), ). - Watches( - &source.Kind{Type: &corev1.ConfigMap{}}, + WatchesMetadata( + &corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(r.resourceToClusterResourceSet), - builder.OnlyMetadata, builder.WithPredicates( resourcepredicates.ResourceCreateOrUpdate(ctrl.LoggerFrom(ctx)), ), ). - Watches( - &source.Kind{Type: &corev1.Secret{}}, + WatchesMetadata( + &corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(r.resourceToClusterResourceSet), - builder.OnlyMetadata, builder.WithPredicates( resourcepredicates.ResourceCreateOrUpdate(ctrl.LoggerFrom(ctx)), ), @@ -430,7 +427,7 @@ func (r *ClusterResourceSetReconciler) ensureResourceOwnerRef(ctx context.Contex } // clusterToClusterResourceSet is mapper function that maps clusters to ClusterResourceSet. -func (r *ClusterResourceSetReconciler) clusterToClusterResourceSet(o client.Object) []ctrl.Request { +func (r *ClusterResourceSetReconciler) clusterToClusterResourceSet(ctx context.Context, o client.Object) []ctrl.Request { result := []ctrl.Request{} cluster, ok := o.(*clusterv1.Cluster) @@ -439,7 +436,7 @@ func (r *ClusterResourceSetReconciler) clusterToClusterResourceSet(o client.Obje } resourceList := &addonsv1.ClusterResourceSetList{} - if err := r.Client.List(context.TODO(), resourceList, client.InNamespace(cluster.Namespace)); err != nil { + if err := r.Client.List(ctx, resourceList, client.InNamespace(cluster.Namespace)); err != nil { return nil } @@ -468,7 +465,7 @@ func (r *ClusterResourceSetReconciler) clusterToClusterResourceSet(o client.Obje } // resourceToClusterResourceSet is mapper function that maps resources to ClusterResourceSet. -func (r *ClusterResourceSetReconciler) resourceToClusterResourceSet(o client.Object) []ctrl.Request { +func (r *ClusterResourceSetReconciler) resourceToClusterResourceSet(ctx context.Context, o client.Object) []ctrl.Request { result := []ctrl.Request{} // Add all ClusterResourceSet owners. @@ -491,7 +488,7 @@ func (r *ClusterResourceSetReconciler) resourceToClusterResourceSet(o client.Obj } crsList := &addonsv1.ClusterResourceSetList{} - if err := r.Client.List(context.TODO(), crsList, client.InNamespace(o.GetNamespace())); err != nil { + if err := r.Client.List(ctx, crsList, client.InNamespace(o.GetNamespace())); err != nil { return nil } objKind, err := apiutil.GVKForObject(o, r.Client.Scheme()) diff --git a/exp/addons/internal/controllers/clusterresourcesetbinding_controller.go b/exp/addons/internal/controllers/clusterresourcesetbinding_controller.go index 4f3b8e8be28d..3ebdb70d9725 100644 --- a/exp/addons/internal/controllers/clusterresourcesetbinding_controller.go +++ b/exp/addons/internal/controllers/clusterresourcesetbinding_controller.go @@ -27,7 +27,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1" @@ -52,7 +51,7 @@ func (r *ClusterResourceSetBindingReconciler) SetupWithManager(ctx context.Conte err := ctrl.NewControllerManagedBy(mgr). For(&addonsv1.ClusterResourceSetBinding{}). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(r.clusterToClusterResourceSetBinding), ). WithOptions(options). @@ -107,7 +106,7 @@ func (r *ClusterResourceSetBindingReconciler) Reconcile(ctx context.Context, req } // clusterToClusterResourceSetBinding is mapper function that maps clusters to ClusterResourceSetBinding. -func (r *ClusterResourceSetBindingReconciler) clusterToClusterResourceSetBinding(o client.Object) []ctrl.Request { +func (r *ClusterResourceSetBindingReconciler) clusterToClusterResourceSetBinding(_ context.Context, o client.Object) []ctrl.Request { return []reconcile.Request{ { NamespacedName: client.ObjectKey{ diff --git a/exp/api/v1beta1/machinepool_webhook.go b/exp/api/v1beta1/machinepool_webhook.go index 0b2db7c15487..58dc05ef7758 100644 --- a/exp/api/v1beta1/machinepool_webhook.go +++ b/exp/api/v1beta1/machinepool_webhook.go @@ -26,6 +26,7 @@ import ( "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/feature" @@ -75,22 +76,22 @@ func (m *MachinePool) Default() { } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachinePool) ValidateCreate() error { - return m.validate(nil) +func (m *MachinePool) ValidateCreate() (admission.Warnings, error) { + return nil, m.validate(nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachinePool) ValidateUpdate(old runtime.Object) error { +func (m *MachinePool) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { oldMP, ok := old.(*MachinePool) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a MachinePool but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachinePool but got a %T", old)) } - return m.validate(oldMP) + return nil, m.validate(oldMP) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *MachinePool) ValidateDelete() error { - return m.validate(nil) +func (m *MachinePool) ValidateDelete() (admission.Warnings, error) { + return nil, m.validate(nil) } func (m *MachinePool) validate(old *MachinePool) error { diff --git a/exp/api/v1beta1/machinepool_webhook_test.go b/exp/api/v1beta1/machinepool_webhook_test.go index 7fd1eca0ac98..987750ee532d 100644 --- a/exp/api/v1beta1/machinepool_webhook_test.go +++ b/exp/api/v1beta1/machinepool_webhook_test.go @@ -99,12 +99,17 @@ func TestMachinePoolBootstrapValidation(t *testing.T) { }, }, } + if tt.expectErr { - g.Expect(m.ValidateCreate()).NotTo(Succeed()) - g.Expect(m.ValidateUpdate(m)).NotTo(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(m.ValidateCreate()).To(Succeed()) - g.Expect(m.ValidateUpdate(m)).To(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -168,11 +173,15 @@ func TestMachinePoolNamespaceValidation(t *testing.T) { } if tt.expectErr { - g.Expect(m.ValidateCreate()).NotTo(Succeed()) - g.Expect(m.ValidateUpdate(m)).NotTo(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(m.ValidateCreate()).To(Succeed()) - g.Expect(m.ValidateUpdate(m)).To(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -228,10 +237,11 @@ func TestMachinePoolClusterNameImmutable(t *testing.T) { }, } + _, err := newMP.ValidateUpdate(oldMP) if tt.expectErr { - g.Expect(newMP.ValidateUpdate(oldMP)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(newMP.ValidateUpdate(oldMP)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -284,11 +294,15 @@ func TestMachinePoolVersionValidation(t *testing.T) { } if tt.expectErr { - g.Expect(m.ValidateCreate()).NotTo(Succeed()) - g.Expect(m.ValidateUpdate(m)).NotTo(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).To(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(m.ValidateCreate()).To(Succeed()) - g.Expect(m.ValidateUpdate(m)).To(Succeed()) + _, err := m.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) + _, err = m.ValidateUpdate(m) + g.Expect(err).NotTo(HaveOccurred()) } }) } diff --git a/exp/internal/controllers/machinepool_controller.go b/exp/internal/controllers/machinepool_controller.go index 404865b7bbfb..d431206cc7a5 100644 --- a/exp/internal/controllers/machinepool_controller.go +++ b/exp/internal/controllers/machinepool_controller.go @@ -31,12 +31,12 @@ import ( "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/api/v1beta1/index" @@ -73,6 +73,7 @@ type MachinePoolReconciler struct { controller controller.Controller recorder record.EventRecorder externalWatchers sync.Map + cache cache.Cache } func (r *MachinePoolReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -86,7 +87,7 @@ func (r *MachinePoolReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(clusterToMachinePools), // TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources? builder.WithPredicates( @@ -103,6 +104,7 @@ func (r *MachinePoolReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M r.controller = c r.recorder = mgr.GetEventRecorderFor("machinepool-controller") + r.cache = mgr.GetCache() return nil } @@ -314,7 +316,7 @@ func (r *MachinePoolReconciler) watchClusterNodes(ctx context.Context, cluster * }) } -func (r *MachinePoolReconciler) nodeToMachinePool(o client.Object) []reconcile.Request { +func (r *MachinePoolReconciler) nodeToMachinePool(ctx context.Context, o client.Object) []reconcile.Request { node, ok := o.(*corev1.Node) if !ok { panic(fmt.Sprintf("Expected a Node but got a %T", o)) @@ -336,7 +338,7 @@ func (r *MachinePoolReconciler) nodeToMachinePool(o client.Object) []reconcile.R // Match by nodeName and status.nodeRef.name. machinePoolList := &expv1.MachinePoolList{} if err := r.Client.List( - context.TODO(), + ctx, machinePoolList, append(filters, client.MatchingFields{index.MachinePoolNodeNameField: node.Name})...); err != nil { return nil @@ -354,7 +356,7 @@ func (r *MachinePoolReconciler) nodeToMachinePool(o client.Object) []reconcile.R } machinePoolList = &expv1.MachinePoolList{} if err := r.Client.List( - context.TODO(), + ctx, machinePoolList, append(filters, client.MatchingFields{index.MachinePoolProviderIDField: node.Spec.ProviderID})...); err != nil { return nil diff --git a/exp/internal/controllers/machinepool_controller_phases.go b/exp/internal/controllers/machinepool_controller_phases.go index cb60b4429569..5dc8f0bbed62 100644 --- a/exp/internal/controllers/machinepool_controller_phases.go +++ b/exp/internal/controllers/machinepool_controller_phases.go @@ -153,8 +153,8 @@ func (r *MachinePoolReconciler) reconcileExternal(ctx context.Context, cluster * if !loaded && r.controller != nil { log.Info("Adding watcher on external object", "groupVersionKind", obj.GroupVersionKind()) err := r.controller.Watch( - &source.Kind{Type: obj}, - &handler.EnqueueRequestForOwner{OwnerType: &expv1.MachinePool{}}, + source.Kind(r.cache, obj), + handler.EnqueueRequestForOwner(r.Client.Scheme(), r.Client.RESTMapper(), &expv1.MachinePool{}), ) if err != nil { r.externalWatchers.Delete(obj.GroupVersionKind().String()) diff --git a/exp/internal/controllers/machinepool_controller_phases_test.go b/exp/internal/controllers/machinepool_controller_phases_test.go index dee57c28ed9e..28cb0190301f 100644 --- a/exp/internal/controllers/machinepool_controller_phases_test.go +++ b/exp/internal/controllers/machinepool_controller_phases_test.go @@ -460,6 +460,7 @@ func TestReconcileMachinePoolPhases(t *testing.T) { // Set Deletion Timestamp. machinepool.SetDeletionTimestamp(&deletionTimestamp) + machinepool.Finalizers = []string{expv1.MachinePoolFinalizer} r := &MachinePoolReconciler{ Client: fake.NewClientBuilder().WithObjects(defaultCluster, defaultKubeconfigSecret, machinepool, bootstrapConfig, infraConfig, builder.TestBootstrapConfigCRD, builder.TestInfrastructureMachineTemplateCRD).Build(), diff --git a/exp/internal/controllers/machinepool_controller_test.go b/exp/internal/controllers/machinepool_controller_test.go index a771d25c3bcd..c4e2a21d4894 100644 --- a/exp/internal/controllers/machinepool_controller_test.go +++ b/exp/internal/controllers/machinepool_controller_test.go @@ -223,7 +223,7 @@ func TestMachinePoolOwnerReference(t *testing.T) { machinePoolInvalidCluster, machinePoolValidCluster, machinePoolValidMachinePool, - ).Build() + ).WithStatusSubresource(&expv1.MachinePool{}).Build() mr := &MachinePoolReconciler{ Client: fakeClient, APIReader: fakeClient, @@ -420,7 +420,7 @@ func TestReconcileMachinePoolRequest(t *testing.T) { bootstrapConfig, builder.TestBootstrapConfigCRD, builder.TestInfrastructureMachineTemplateCRD, - ).Build() + ).WithStatusSubresource(&expv1.MachinePool{}).Build() r := &MachinePoolReconciler{ Client: clientFake, @@ -591,7 +591,7 @@ func TestRemoveMachinePoolFinalizerAfterDeleteReconcile(t *testing.T) { } key := client.ObjectKey{Namespace: m.Namespace, Name: m.Name} mr := &MachinePoolReconciler{ - Client: fake.NewClientBuilder().WithObjects(testCluster, m).Build(), + Client: fake.NewClientBuilder().WithObjects(testCluster, m).WithStatusSubresource(&expv1.MachinePool{}).Build(), } _, err := mr.Reconcile(ctx, reconcile.Request{NamespacedName: key}) g.Expect(err).ToNot(HaveOccurred()) @@ -858,7 +858,7 @@ func TestMachinePoolConditions(t *testing.T) { &nodes.Items[1], builder.TestBootstrapConfigCRD, builder.TestInfrastructureMachineTemplateCRD, - ).Build() + ).WithStatusSubresource(&expv1.MachinePool{}).Build() r := &MachinePoolReconciler{ Client: clientFake, diff --git a/exp/ipam/internal/webhooks/ipaddress.go b/exp/ipam/internal/webhooks/ipaddress.go index 6cf6b056ae9a..ca435b81e379 100644 --- a/exp/ipam/internal/webhooks/ipaddress.go +++ b/exp/ipam/internal/webhooks/ipaddress.go @@ -30,6 +30,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" ) @@ -53,34 +54,34 @@ type IPAddress struct { var _ webhook.CustomValidator = &IPAddress{} // ValidateCreate implements webhook.CustomValidator. -func (webhook *IPAddress) ValidateCreate(ctx context.Context, obj runtime.Object) error { +func (webhook *IPAddress) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { ip, ok := obj.(*ipamv1.IPAddress) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddress but got a %T", obj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddress but got a %T", obj)) } - return webhook.validate(ctx, ip) + return nil, webhook.validate(ctx, ip) } // ValidateUpdate implements webhook.CustomValidator. -func (webhook *IPAddress) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) error { +func (webhook *IPAddress) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { oldIP, ok := oldObj.(*ipamv1.IPAddress) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddress but got a %T", oldObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddress but got a %T", oldObj)) } newIP, ok := newObj.(*ipamv1.IPAddress) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddress but got a %T", newObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddress but got a %T", newObj)) } if !reflect.DeepEqual(oldIP.Spec, newIP.Spec) { - return field.Forbidden(field.NewPath("spec"), "the spec of IPAddress is immutable") + return nil, field.Forbidden(field.NewPath("spec"), "the spec of IPAddress is immutable") } - return nil + return nil, nil } // ValidateDelete implements webhook.CustomValidator. -func (webhook *IPAddress) ValidateDelete(_ context.Context, _ runtime.Object) error { - return nil +func (webhook *IPAddress) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil } func (webhook *IPAddress) validate(ctx context.Context, ip *ipamv1.IPAddress) error { diff --git a/exp/ipam/internal/webhooks/ipaddress_test.go b/exp/ipam/internal/webhooks/ipaddress_test.go index 5cdad9a5ddcf..9052181118e6 100644 --- a/exp/ipam/internal/webhooks/ipaddress_test.go +++ b/exp/ipam/internal/webhooks/ipaddress_test.go @@ -222,10 +222,11 @@ func TestIPAddressValidateUpdate(t *testing.T) { wh := IPAddress{ Client: fake.NewClientBuilder().WithScheme(scheme).WithObjects(tt.extraObjs...).Build(), } + _, err := wh.ValidateUpdate(context.Background(), &tt.oldIP, &tt.newIP) if tt.expectErr { - g.Expect(wh.ValidateUpdate(context.Background(), &tt.oldIP, &tt.newIP)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(wh.ValidateUpdate(context.Background(), &tt.oldIP, &tt.newIP)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } diff --git a/exp/ipam/internal/webhooks/ipaddressclaim.go b/exp/ipam/internal/webhooks/ipaddressclaim.go index c009eb2398a1..b2b8ceddc655 100644 --- a/exp/ipam/internal/webhooks/ipaddressclaim.go +++ b/exp/ipam/internal/webhooks/ipaddressclaim.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" ) @@ -47,43 +48,43 @@ type IPAddressClaim struct { var _ webhook.CustomValidator = &IPAddressClaim{} // ValidateCreate implements webhook.CustomValidator. -func (webhook *IPAddressClaim) ValidateCreate(_ context.Context, obj runtime.Object) error { +func (webhook *IPAddressClaim) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { claim, ok := obj.(*ipamv1.IPAddressClaim) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddressClaim but got a %T", obj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddressClaim but got a %T", obj)) } if claim.Spec.PoolRef.APIGroup == nil { - return field.Invalid( + return nil, field.Invalid( field.NewPath("spec.poolRef.apiGroup"), claim.Spec.PoolRef.APIGroup, "the pool reference needs to contain a group") } - return nil + return nil, nil } // ValidateUpdate implements webhook.CustomValidator. -func (webhook *IPAddressClaim) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) error { +func (webhook *IPAddressClaim) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { oldClaim, ok := oldObj.(*ipamv1.IPAddressClaim) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddressClaim but got a %T", oldObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddressClaim but got a %T", oldObj)) } newClaim, ok := newObj.(*ipamv1.IPAddressClaim) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddressClaim but got a %T", newObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an IPAddressClaim but got a %T", newObj)) } if !reflect.DeepEqual(oldClaim.Spec, newClaim.Spec) { - return field.Forbidden( + return nil, field.Forbidden( field.NewPath("spec"), "the spec of IPAddressClaim is immutable", ) } - return nil + return nil, nil } // ValidateDelete implements webhook.CustomValidator. -func (webhook *IPAddressClaim) ValidateDelete(_ context.Context, _ runtime.Object) error { - return nil +func (webhook *IPAddressClaim) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil } diff --git a/exp/ipam/internal/webhooks/ipaddressclaim_test.go b/exp/ipam/internal/webhooks/ipaddressclaim_test.go index 2b067978877f..dc338a64af60 100644 --- a/exp/ipam/internal/webhooks/ipaddressclaim_test.go +++ b/exp/ipam/internal/webhooks/ipaddressclaim_test.go @@ -65,10 +65,11 @@ func TestIPAddressClaimValidateCreate(t *testing.T) { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) wh := IPAddressClaim{} + _, err := wh.ValidateCreate(context.Background(), &tt.claim) if tt.expectErr { - g.Expect(wh.ValidateCreate(context.Background(), &tt.claim)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(wh.ValidateCreate(context.Background(), &tt.claim)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -113,10 +114,11 @@ func TestIPAddressClaimValidateUpdate(t *testing.T) { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) wh := IPAddressClaim{} + _, err := wh.ValidateUpdate(context.Background(), &tt.oldClaim, &tt.newClaim) if tt.expectErr { - g.Expect(wh.ValidateUpdate(context.Background(), &tt.oldClaim, &tt.newClaim)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(wh.ValidateUpdate(context.Background(), &tt.oldClaim, &tt.newClaim)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } diff --git a/exp/runtime/internal/controllers/extensionconfig_controller.go b/exp/runtime/internal/controllers/extensionconfig_controller.go index 361a5c1c00bb..95770ba053cc 100644 --- a/exp/runtime/internal/controllers/extensionconfig_controller.go +++ b/exp/runtime/internal/controllers/extensionconfig_controller.go @@ -27,12 +27,10 @@ import ( "k8s.io/apimachinery/pkg/types" kerrors "k8s.io/apimachinery/pkg/util/errors" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1" @@ -64,10 +62,9 @@ type Reconciler struct { func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { err := ctrl.NewControllerManagedBy(mgr). For(&runtimev1.ExtensionConfig{}). - Watches( - &source.Kind{Type: &corev1.Secret{}}, + WatchesMetadata( + &corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(r.secretToExtensionConfig), - builder.OnlyMetadata, ). WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). @@ -188,14 +185,14 @@ func (r *Reconciler) reconcileDelete(ctx context.Context, extensionConfig *runti // secretToExtensionConfig maps a secret to ExtensionConfigs with the corresponding InjectCAFromSecretAnnotation // to reconcile them on updates of the secrets. -func (r *Reconciler) secretToExtensionConfig(secret client.Object) []reconcile.Request { +func (r *Reconciler) secretToExtensionConfig(ctx context.Context, secret client.Object) []reconcile.Request { result := []ctrl.Request{} extensionConfigs := runtimev1.ExtensionConfigList{} indexKey := secret.GetNamespace() + "/" + secret.GetName() if err := r.Client.List( - context.TODO(), + ctx, &extensionConfigs, client.MatchingFields{injectCAFromSecretAnnotationField: indexKey}, ); err != nil { diff --git a/exp/runtime/internal/controllers/warmup.go b/exp/runtime/internal/controllers/warmup.go index 72b2860bd5cb..224ca6336de8 100644 --- a/exp/runtime/internal/controllers/warmup.go +++ b/exp/runtime/internal/controllers/warmup.go @@ -72,7 +72,7 @@ func (r *warmupRunnable) Start(ctx context.Context) error { ctx, cancel := context.WithTimeout(ctx, r.warmupTimeout) defer cancel() - err := wait.PollImmediateWithContext(ctx, r.warmupInterval, r.warmupTimeout, func(ctx context.Context) (done bool, err error) { + err := wait.PollUntilContextTimeout(ctx, r.warmupInterval, r.warmupTimeout, true, func(ctx context.Context) (done bool, err error) { if err = warmupRegistry(ctx, r.Client, r.APIReader, r.RuntimeClient); err != nil { log.Error(err, "ExtensionConfig registry warmup failed") return false, nil diff --git a/exp/runtime/server/server.go b/exp/runtime/server/server.go index 1e2370bb7c8a..73b6a757b779 100644 --- a/exp/runtime/server/server.go +++ b/exp/runtime/server/server.go @@ -19,6 +19,7 @@ package server import ( "context" + "crypto/tls" "encoding/json" "fmt" "io" @@ -37,15 +38,13 @@ import ( runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ) -const tlsVersion13 = "1.3" - // DefaultPort is the default port that the webhook server serves. var DefaultPort = 9443 // Server is a runtime webhook server. type Server struct { catalog *runtimecatalog.Catalog - server *webhook.Server + server webhook.Server handlers map[string]ExtensionHandler } @@ -82,15 +81,21 @@ func New(options Options) (*Server, error) { options.CertDir = filepath.Join(os.TempDir(), "k8s-webhook-server", "serving-certs") } - webhookServer := &webhook.Server{ - Port: options.Port, - Host: options.Host, - CertDir: options.CertDir, - CertName: "tls.crt", - KeyName: "tls.key", - WebhookMux: http.NewServeMux(), - TLSMinVersion: tlsVersion13, - } + webhookServer := webhook.NewServer( + webhook.Options{ + Port: options.Port, + Host: options.Host, + CertDir: options.CertDir, + CertName: "tls.crt", + KeyName: "tls.key", + WebhookMux: http.NewServeMux(), + TLSOpts: []func(*tls.Config){ + func(cfg *tls.Config) { + cfg.MinVersion = tls.VersionTLS13 + }, + }, + }, + ) return &Server{ catalog: options.Catalog, @@ -230,7 +235,7 @@ func (s *Server) Start(ctx context.Context) error { s.server.Register(handlerPath, http.HandlerFunc(wrappedHandler)) } - return s.server.StartStandalone(ctx, nil) + return s.server.Start(ctx) } // discoveryHandler generates a discovery handler based on a list of handlers. diff --git a/exp/util/util.go b/exp/util/util.go index 42e7ce4e5f5d..d2904603e0ff 100644 --- a/exp/util/util.go +++ b/exp/util/util.go @@ -63,7 +63,7 @@ func GetMachinePoolByName(ctx context.Context, c client.Client, namespace, name // MachinePool events and returns reconciliation requests for an infrastructure provider object. func MachinePoolToInfrastructureMapFunc(gvk schema.GroupVersionKind, log logr.Logger) handler.MapFunc { log = log.WithValues("machine-pool-to-infra-map-func", gvk.String()) - return func(o client.Object) []reconcile.Request { + return func(_ context.Context, o client.Object) []reconcile.Request { m, ok := o.(*expv1.MachinePool) if !ok { log.V(4).Info("Not a machine pool", "Object", klog.KObj(o)) diff --git a/feature/feature.go b/feature/feature.go index 416594118122..79ab03fc305d 100644 --- a/feature/feature.go +++ b/feature/feature.go @@ -55,11 +55,6 @@ const ( // // alpha: v1.1 KubeadmBootstrapFormatIgnition featuregate.Feature = "KubeadmBootstrapFormatIgnition" - - // LazyRestmapper is a feature gate for the Lazy Restmapper functionality. - // - // alpha: v1.4 - LazyRestmapper featuregate.Feature = "LazyRestmapper" ) func init() { @@ -75,5 +70,4 @@ var defaultClusterAPIFeatureGates = map[featuregate.Feature]featuregate.FeatureS ClusterTopology: {Default: false, PreRelease: featuregate.Alpha}, KubeadmBootstrapFormatIgnition: {Default: false, PreRelease: featuregate.Alpha}, RuntimeSDK: {Default: false, PreRelease: featuregate.Alpha}, - LazyRestmapper: {Default: false, PreRelease: featuregate.Alpha}, } diff --git a/go.mod b/go.mod index 8886eacfb404..15a41e226b50 100644 --- a/go.mod +++ b/go.mod @@ -27,22 +27,22 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 github.com/valyala/fastjson v1.6.4 - go.etcd.io/etcd/api/v3 v3.5.6 - go.etcd.io/etcd/client/v3 v3.5.6 + go.etcd.io/etcd/api/v3 v3.5.7 + go.etcd.io/etcd/client/v3 v3.5.7 golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.8.0 google.golang.org/grpc v1.52.0 - k8s.io/api v0.26.1 - k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.1 - k8s.io/apiserver v0.26.1 - k8s.io/client-go v0.26.1 - k8s.io/cluster-bootstrap v0.25.0 - k8s.io/component-base v0.26.1 - k8s.io/klog/v2 v2.80.1 - k8s.io/kubectl v0.25.0 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 - sigs.k8s.io/controller-runtime v0.14.6 + k8s.io/api v0.27.2 + k8s.io/apiextensions-apiserver v0.27.2 + k8s.io/apimachinery v0.27.2 + k8s.io/apiserver v0.27.2 + k8s.io/client-go v0.27.2 + k8s.io/cluster-bootstrap v0.27.2 + k8s.io/component-base v0.27.2 + k8s.io/klog/v2 v2.90.1 + k8s.io/kubectl v0.27.2 + k8s.io/utils v0.0.0-20230209194617-a36077c30491 + sigs.k8s.io/controller-runtime v0.15.0 sigs.k8s.io/yaml v1.3.0 ) @@ -60,14 +60,14 @@ require ( github.com/coredns/caddy v1.1.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect - github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/coreos/go-systemd/v22 v22.4.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-errors/errors v1.0.1 // indirect - github.com/go-logr/zapr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -95,7 +95,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect + github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect @@ -103,11 +103,10 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/prometheus/client_golang v1.15.1 - github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rivo/uniseg v0.4.2 // indirect - github.com/russross/blackfriday v1.5.2 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect @@ -116,7 +115,7 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/vincent-petithory/dataurl v1.0.0 // indirect github.com/xlab/treeprint v1.1.0 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect @@ -135,11 +134,11 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/cli-runtime v0.25.0 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/kustomize/api v0.12.1 // indirect - sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect + k8s.io/cli-runtime v0.27.2 // indirect + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/api v0.13.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) @@ -148,8 +147,9 @@ require ( github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/gnostic v0.6.9 // indirect - github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect golang.org/x/tools v0.9.1 // indirect ) diff --git a/go.sum b/go.sum index 09d75812fd1a..99be87f51fc1 100644 --- a/go.sum +++ b/go.sum @@ -54,10 +54,7 @@ github.com/ajeddeloh/go-json v0.0.0-20160803184958-73d058cf8437/go.mod h1:otnto4 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/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 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= @@ -86,7 +83,6 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= @@ -99,7 +95,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/corefile-migration v1.0.20 h1:MdOkT6F3ehju/n9tgxlGct8XAajOX2vN+wG7To4BWSI= @@ -113,13 +108,13 @@ github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= +github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -130,8 +125,6 @@ github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -139,9 +132,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -163,30 +154,24 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-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-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -272,8 +257,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -328,38 +313,33 @@ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 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/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -396,12 +376,11 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= @@ -410,7 +389,6 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -438,29 +416,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= @@ -470,10 +438,9 @@ github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -486,8 +453,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV 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/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -553,12 +518,12 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd/api/v3 v3.5.6 h1:Cy2qx3npLcYqTKqGJzMypnMv2tiRyifZJ17BlWIWA7A= -go.etcd.io/etcd/api/v3 v3.5.6/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= -go.etcd.io/etcd/client/pkg/v3 v3.5.6 h1:TXQWYceBKqLp4sa87rcPs11SXxUA/mHwH975v+BDvLU= -go.etcd.io/etcd/client/pkg/v3 v3.5.6/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= -go.etcd.io/etcd/client/v3 v3.5.6 h1:coLs69PWCXE9G4FKquzNaSHrRyMCAXwF+IX1tAPVO8E= -go.etcd.io/etcd/client/v3 v3.5.6/go.mod h1:f6GRinRMCsFVv9Ht42EyY7nfsVGwrNO0WEoS2pRKzQk= +go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= +go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= +go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= +go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= +go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= +go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= 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= @@ -572,15 +537,13 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org v0.0.0-20160314031811-03efcb870d84/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= @@ -621,7 +584,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -649,7 +611,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -710,7 +671,6 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -720,7 +680,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -733,8 +692,6 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -742,14 +699,11 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -794,12 +748,10 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -835,7 +787,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= @@ -909,7 +861,6 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= @@ -931,9 +882,7 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -956,6 +905,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -968,7 +918,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -979,8 +928,6 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/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= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -988,43 +935,42 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= -k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= -k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= -k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= -k8s.io/cli-runtime v0.25.0 h1:XBnTc2Fi+w818jcJGzhiJKQuXl8479sZ4FhtV5hVJ1Q= -k8s.io/cli-runtime v0.25.0/go.mod h1:bHOI5ZZInRHhbq12OdUiYZQN8ml8aKZLwQgt9QlLINw= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -k8s.io/cluster-bootstrap v0.25.0 h1:KJ2/r0dV+bLfTK5EBobAVKvjGel3N4Qqh3bvnzh9qPk= -k8s.io/cluster-bootstrap v0.25.0/go.mod h1:x/TCtY3EiuR/rODkA3SvVQT3uSssQLf9cXcmSjdDTe0= -k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= -k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kubectl v0.25.0 h1:/Wn1cFqo8ik3iee1EvpxYre3bkWsGLXzLQI6uCCAkQc= -k8s.io/kubectl v0.25.0/go.mod h1:n16ULWsOl2jmQpzt2o7Dud1t4o0+Y186ICb4O+GwKAU= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= +k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= +k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= +k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= +k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= +k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= +k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= +k8s.io/cli-runtime v0.27.2 h1:9HI8gfReNujKXt16tGOAnb8b4NZ5E+e0mQQHKhFGwYw= +k8s.io/cli-runtime v0.27.2/go.mod h1:9UecpyPDTkhiYY4d9htzRqN+rKomJgyb4wi0OfrmCjw= +k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= +k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/cluster-bootstrap v0.27.2 h1:OL3onrOwrUD7NQxBUqQwTl1Uu2GQKCkw9BMHpc4PbiA= +k8s.io/cluster-bootstrap v0.27.2/go.mod h1:b++PF0mjUOiTKdPQFlDw7p4V2VquANZ8SfhAwzxZJFM= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= +k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/kubectl v0.27.2 h1:sSBM2j94MHBFRWfHIWtEXWCicViQzZsb177rNsKBhZg= +k8s.io/kubectl v0.27.2/go.mod h1:GCOODtxPcrjh+EC611MqREkU8RjYBh10ldQCQ6zpFKw= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= -sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= -sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= -sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= -sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.13.2 h1:kejWfLeJhUsTGioDoFNJET5LQe/ajzXhJGYoU+pJsiA= +sigs.k8s.io/kustomize/api v0.13.2/go.mod h1:DUp325VVMFVcQSq+ZxyDisA8wtldwHxLZbr1g94UHsw= +sigs.k8s.io/kustomize/kyaml v0.14.1 h1:c8iibius7l24G2wVAGZn/Va2wNys03GXLjYVIcFVxKA= +sigs.k8s.io/kustomize/kyaml v0.14.1/go.mod h1:AN1/IpawKilWD7V+YvQwRGUvuUOOWpjsHu6uHwonSF4= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 9927d343bfd0..8d4c533eb632 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -16,19 +16,19 @@ require ( golang.org/x/tools v0.9.1 google.golang.org/api v0.107.0 helm.sh/helm/v3 v3.11.1 - k8s.io/api v0.26.1 - k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.1 - k8s.io/client-go v0.26.1 - k8s.io/klog/v2 v2.80.1 - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 + k8s.io/api v0.27.2 + k8s.io/apiextensions-apiserver v0.27.2 + k8s.io/apimachinery v0.27.2 + k8s.io/client-go v0.27.2 + k8s.io/klog/v2 v2.90.1 + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f + k8s.io/utils v0.0.0-20230209194617-a36077c30491 sigs.k8s.io/cluster-api v0.0.0-00010101000000-000000000000 sigs.k8s.io/cluster-api/test v0.0.0-00010101000000-000000000000 - sigs.k8s.io/controller-runtime v0.14.6 - sigs.k8s.io/controller-tools v0.11.4 + sigs.k8s.io/controller-runtime v0.15.0 + sigs.k8s.io/controller-tools v0.12.0 sigs.k8s.io/kubebuilder/docs/book/utils v0.0.0-20211028165026-57688c578b5d - sigs.k8s.io/kustomize/api v0.12.1 + sigs.k8s.io/kustomize/api v0.13.2 sigs.k8s.io/yaml v1.3.0 ) @@ -64,10 +64,10 @@ require ( github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-errors/errors v1.0.1 // indirect + github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.2.4 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gobuffalo/flect v1.0.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -114,7 +114,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/prometheus/client_golang v1.15.1 // indirect - github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect @@ -148,12 +148,12 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiserver v0.26.1 // indirect - k8s.io/cli-runtime v0.26.0 // indirect - k8s.io/cluster-bootstrap v0.25.0 // indirect - k8s.io/component-base v0.26.1 // indirect + k8s.io/apiserver v0.27.2 // indirect + k8s.io/cli-runtime v0.27.2 // indirect + k8s.io/cluster-bootstrap v0.27.2 // indirect + k8s.io/component-base v0.27.2 // indirect oras.land/oras-go v1.2.2 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/hack/tools/go.sum b/hack/tools/go.sum index 95be23ff1528..417ef71304a2 100644 --- a/hack/tools/go.sum +++ b/hack/tools/go.sum @@ -116,6 +116,7 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -164,8 +165,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-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-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -175,13 +176,11 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -268,7 +267,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -352,18 +351,18 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -441,8 +440,8 @@ github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -459,7 +458,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -546,7 +545,7 @@ go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee33 go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -916,6 +915,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -938,7 +938,7 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/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= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= helm.sh/helm/v3 v3.11.1 h1:cmL9fFohOoNQf+wnp2Wa0OhNFH0KFnSzEkVxi3fcc3I= helm.sh/helm/v3 v3.11.1/go.mod h1:z/Bu/BylToGno/6dtNGuSmjRqxKq5gaH+FU0BPO+AQ8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -948,45 +948,45 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= -k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= -k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= -k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= -k8s.io/cli-runtime v0.26.0 h1:aQHa1SyUhpqxAw1fY21x2z2OS5RLtMJOCj7tN4oq8mw= -k8s.io/cli-runtime v0.26.0/go.mod h1:o+4KmwHzO/UK0wepE1qpRk6l3o60/txUZ1fEXWGIKTY= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -k8s.io/cluster-bootstrap v0.25.0 h1:KJ2/r0dV+bLfTK5EBobAVKvjGel3N4Qqh3bvnzh9qPk= -k8s.io/cluster-bootstrap v0.25.0/go.mod h1:x/TCtY3EiuR/rODkA3SvVQT3uSssQLf9cXcmSjdDTe0= -k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= -k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= +k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= +k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= +k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= +k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= +k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= +k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= +k8s.io/cli-runtime v0.27.2 h1:9HI8gfReNujKXt16tGOAnb8b4NZ5E+e0mQQHKhFGwYw= +k8s.io/cli-runtime v0.27.2/go.mod h1:9UecpyPDTkhiYY4d9htzRqN+rKomJgyb4wi0OfrmCjw= +k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= +k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/cluster-bootstrap v0.27.2 h1:OL3onrOwrUD7NQxBUqQwTl1Uu2GQKCkw9BMHpc4PbiA= +k8s.io/cluster-bootstrap v0.27.2/go.mod h1:b++PF0mjUOiTKdPQFlDw7p4V2VquANZ8SfhAwzxZJFM= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= +k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.2 h1:0E9tOHUfrNH7TCDk5KU0jVBEzCqbfdyuVfGmJ7ZeRPE= oras.land/oras-go v1.2.2/go.mod h1:Apa81sKoZPpP7CDciE006tSZ0x3Q3+dOoBcMZ/aNxvw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= -sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -sigs.k8s.io/controller-tools v0.11.4 h1:jqXJ/Xb6yBgbgcBbw1YoC3rC+Bt1XZWiLjj0ZHv/GrU= -sigs.k8s.io/controller-tools v0.11.4/go.mod h1:qcfX7jfcfYD/b7lAhvqAyTbt/px4GpvN88WKLFFv7p8= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/controller-tools v0.12.0 h1:TY6CGE6+6hzO7hhJFte65ud3cFmmZW947jajXkuDfBw= +sigs.k8s.io/controller-tools v0.12.0/go.mod h1:rXlpTfFHZMpZA8aGq9ejArgZiieHd+fkk/fTatY8A2M= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kubebuilder/docs/book/utils v0.0.0-20211028165026-57688c578b5d h1:KLiQzLW3RZJR19+j4pw2h5iioyAyqCkDBEAFdnGa3N8= sigs.k8s.io/kubebuilder/docs/book/utils v0.0.0-20211028165026-57688c578b5d/go.mod h1:NRdZafr4zSCseLQggdvIMXa7umxf+Q+PJzrj3wFwiGE= -sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= -sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= -sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= -sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= +sigs.k8s.io/kustomize/api v0.13.2 h1:kejWfLeJhUsTGioDoFNJET5LQe/ajzXhJGYoU+pJsiA= +sigs.k8s.io/kustomize/api v0.13.2/go.mod h1:DUp325VVMFVcQSq+ZxyDisA8wtldwHxLZbr1g94UHsw= +sigs.k8s.io/kustomize/kyaml v0.14.1 h1:c8iibius7l24G2wVAGZn/Va2wNys03GXLjYVIcFVxKA= +sigs.k8s.io/kustomize/kyaml v0.14.1/go.mod h1:AN1/IpawKilWD7V+YvQwRGUvuUOOWpjsHu6uHwonSF4= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= diff --git a/internal/controllers/cluster/cluster_controller.go b/internal/controllers/cluster/cluster_controller.go index ae61275377f6..5066a3b4eef8 100644 --- a/internal/controllers/cluster/cluster_controller.go +++ b/internal/controllers/cluster/cluster_controller.go @@ -36,7 +36,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/external" @@ -80,7 +79,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt c, err := ctrl.NewControllerManagedBy(mgr). For(&clusterv1.Cluster{}). Watches( - &source.Kind{Type: &clusterv1.Machine{}}, + &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(r.controlPlaneMachineToCluster), ). WithOptions(options). @@ -94,6 +93,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt r.recorder = mgr.GetEventRecorderFor("cluster-controller") r.externalTracker = external.ObjectTracker{ Controller: c, + Cache: mgr.GetCache(), } return nil } @@ -509,7 +509,7 @@ func (r *Reconciler) reconcileControlPlaneInitialized(ctx context.Context, clust // controlPlaneMachineToCluster is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation // for Cluster to update its status.controlPlaneInitialized field. -func (r *Reconciler) controlPlaneMachineToCluster(o client.Object) []ctrl.Request { +func (r *Reconciler) controlPlaneMachineToCluster(ctx context.Context, o client.Object) []ctrl.Request { m, ok := o.(*clusterv1.Machine) if !ok { panic(fmt.Sprintf("Expected a Machine but got a %T", o)) @@ -521,7 +521,7 @@ func (r *Reconciler) controlPlaneMachineToCluster(o client.Object) []ctrl.Reques return nil } - cluster, err := util.GetClusterByName(context.TODO(), r.Client, m.Namespace, m.Spec.ClusterName) + cluster, err := util.GetClusterByName(ctx, r.Client, m.Namespace, m.Spec.ClusterName) if err != nil { return nil } diff --git a/internal/controllers/cluster/cluster_controller_phases.go b/internal/controllers/cluster/cluster_controller_phases.go index 8e15019014d0..e1bd4c31c9a3 100644 --- a/internal/controllers/cluster/cluster_controller_phases.go +++ b/internal/controllers/cluster/cluster_controller_phases.go @@ -123,7 +123,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, cluster *clusterv1.C } // Ensure we add a watcher to the external object. - if err := r.externalTracker.Watch(log, obj, &handler.EnqueueRequestForOwner{OwnerType: &clusterv1.Cluster{}}); err != nil { + if err := r.externalTracker.Watch(log, obj, handler.EnqueueRequestForOwner(r.Client.Scheme(), r.Client.RESTMapper(), &clusterv1.Cluster{})); err != nil { return external.ReconcileOutput{}, err } diff --git a/internal/controllers/cluster/cluster_controller_phases_test.go b/internal/controllers/cluster/cluster_controller_phases_test.go index 2066ab77b22d..1b505d53c96e 100644 --- a/internal/controllers/cluster/cluster_controller_phases_test.go +++ b/internal/controllers/cluster/cluster_controller_phases_test.go @@ -346,6 +346,7 @@ func TestClusterReconciler_reconcilePhase(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-cluster", DeletionTimestamp: &metav1.Time{Time: time.Now().UTC()}, + Finalizers: []string{clusterv1.ClusterFinalizer}, }, Status: clusterv1.ClusterStatus{ InfrastructureReady: true, diff --git a/internal/controllers/cluster/cluster_controller_test.go b/internal/controllers/cluster/cluster_controller_test.go index 2b5721693a74..80a12178347e 100644 --- a/internal/controllers/cluster/cluster_controller_test.go +++ b/internal/controllers/cluster/cluster_controller_test.go @@ -527,7 +527,7 @@ func TestClusterReconcilerNodeRef(t *testing.T) { r := &Reconciler{ Client: fake.NewClientBuilder().WithObjects(cluster, controlPlaneWithNoderef, controlPlaneWithoutNoderef, nonControlPlaneWithNoderef, nonControlPlaneWithoutNoderef).Build(), } - requests := r.controlPlaneMachineToCluster(tt.o) + requests := r.controlPlaneMachineToCluster(ctx, tt.o) g.Expect(requests).To(Equal(tt.want)) }) } diff --git a/internal/controllers/clusterclass/clusterclass_controller.go b/internal/controllers/clusterclass/clusterclass_controller.go index 9f8b483d357a..68c5fa5f50ac 100644 --- a/internal/controllers/clusterclass/clusterclass_controller.go +++ b/internal/controllers/clusterclass/clusterclass_controller.go @@ -37,7 +37,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/external" @@ -79,7 +78,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt Named("clusterclass"). WithOptions(options). Watches( - &source.Kind{Type: &runtimev1.ExtensionConfig{}}, + &runtimev1.ExtensionConfig{}, handler.EnqueueRequestsFromMapFunc(r.extensionConfigToClusterClass), ). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). @@ -388,7 +387,7 @@ func uniqueObjectRefKey(ref *corev1.ObjectReference) string { // extensionConfigToClusterClass maps an ExtensionConfigs to the corresponding ClusterClass to reconcile them on updates // of the ExtensionConfig. -func (r *Reconciler) extensionConfigToClusterClass(o client.Object) []reconcile.Request { +func (r *Reconciler) extensionConfigToClusterClass(ctx context.Context, o client.Object) []reconcile.Request { res := []ctrl.Request{} ext, ok := o.(*runtimev1.ExtensionConfig) @@ -401,11 +400,11 @@ func (r *Reconciler) extensionConfigToClusterClass(o client.Object) []reconcile. if err != nil { return nil } - if err := r.Client.List(context.TODO(), &clusterClasses); err != nil { + if err := r.Client.List(ctx, &clusterClasses); err != nil { return nil } for _, clusterClass := range clusterClasses.Items { - if !matchNamespace(context.TODO(), r.Client, selector, clusterClass.Namespace) { + if !matchNamespace(ctx, r.Client, selector, clusterClass.Namespace) { continue } for _, patch := range clusterClass.Spec.Patches { diff --git a/internal/controllers/clusterclass/suite_test.go b/internal/controllers/clusterclass/suite_test.go index 484c0d3bb81c..525202211bea 100644 --- a/internal/controllers/clusterclass/suite_test.go +++ b/internal/controllers/clusterclass/suite_test.go @@ -62,16 +62,12 @@ func TestMain(m *testing.M) { } } setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { - unstructuredCachingClient, err := client.NewDelegatingClient( - client.NewDelegatingClientInput{ - // Use the default client for write operations. - Client: mgr.GetClient(), - // For read operations, use the same cache used by all the controllers but ensure - // unstructured objects will be also cached (this does not happen with the default client). - CacheReader: mgr.GetCache(), - CacheUnstructured: true, + unstructuredCachingClient, err := client.New(mgr.GetConfig(), client.Options{ + Cache: &client.CacheOptions{ + Reader: mgr.GetCache(), + Unstructured: true, }, - ) + }) if err != nil { panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err)) } diff --git a/internal/controllers/machine/machine_controller.go b/internal/controllers/machine/machine_controller.go index 75d8b78a6ede..3ec241add227 100644 --- a/internal/controllers/machine/machine_controller.go +++ b/internal/controllers/machine/machine_controller.go @@ -40,7 +40,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/api/v1beta1/index" @@ -111,7 +110,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(clusterToMachines), builder.WithPredicates( // TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources? @@ -133,6 +132,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt r.recorder = mgr.GetEventRecorderFor("machine-controller") r.externalTracker = external.ObjectTracker{ Controller: c, + Cache: mgr.GetCache(), } r.ssaCache = ssa.NewCache() return nil @@ -429,7 +429,7 @@ func (r *Reconciler) reconcileDelete(ctx context.Context, cluster *clusterv1.Clu log.Info("Deleting node", "Node", klog.KRef("", m.Status.NodeRef.Name)) var deleteNodeErr error - waitErr := wait.PollImmediate(2*time.Second, r.nodeDeletionRetryTimeout, func() (bool, error) { + waitErr := wait.PollUntilContextTimeout(ctx, 2*time.Second, r.nodeDeletionRetryTimeout, true, func(ctx context.Context) (bool, error) { if deleteNodeErr = r.deleteNode(ctx, cluster, m.Status.NodeRef.Name); deleteNodeErr != nil && !apierrors.IsNotFound(errors.Cause(deleteNodeErr)) { return false, nil } @@ -802,7 +802,7 @@ func (r *Reconciler) watchClusterNodes(ctx context.Context, cluster *clusterv1.C }) } -func (r *Reconciler) nodeToMachine(o client.Object) []reconcile.Request { +func (r *Reconciler) nodeToMachine(ctx context.Context, o client.Object) []reconcile.Request { node, ok := o.(*corev1.Node) if !ok { panic(fmt.Sprintf("Expected a Node but got a %T", o)) @@ -824,7 +824,7 @@ func (r *Reconciler) nodeToMachine(o client.Object) []reconcile.Request { // Match by nodeName and status.nodeRef.name. machineList := &clusterv1.MachineList{} if err := r.Client.List( - context.TODO(), + ctx, machineList, append(filters, client.MatchingFields{index.MachineNodeNameField: node.Name})...); err != nil { return nil @@ -842,7 +842,7 @@ func (r *Reconciler) nodeToMachine(o client.Object) []reconcile.Request { } machineList = &clusterv1.MachineList{} if err := r.Client.List( - context.TODO(), + ctx, machineList, append(filters, client.MatchingFields{index.MachineProviderIDField: node.Spec.ProviderID})...); err != nil { return nil diff --git a/internal/controllers/machine/machine_controller_noderef_test.go b/internal/controllers/machine/machine_controller_noderef_test.go index d1e35459f266..2f7363c4624c 100644 --- a/internal/controllers/machine/machine_controller_noderef_test.go +++ b/internal/controllers/machine/machine_controller_noderef_test.go @@ -17,6 +17,7 @@ limitations under the License. package machine import ( + "context" "fmt" "testing" "time" @@ -142,7 +143,7 @@ func TestGetNode(t *testing.T) { Cluster: util.ObjectKey(testCluster), Watcher: w, Kind: &corev1.Node{}, - EventHandler: handler.EnqueueRequestsFromMapFunc(func(client.Object) []reconcile.Request { + EventHandler: handler.EnqueueRequestsFromMapFunc(func(context.Context, client.Object) []reconcile.Request { return nil }), })).To(Succeed()) diff --git a/internal/controllers/machine/machine_controller_phases.go b/internal/controllers/machine/machine_controller_phases.go index 83c493afc0c4..a0e21ac4f649 100644 --- a/internal/controllers/machine/machine_controller_phases.go +++ b/internal/controllers/machine/machine_controller_phases.go @@ -142,7 +142,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, cluster *clusterv1.C } // Ensure we add a watcher to the external object. - if err := r.externalTracker.Watch(log, obj, &handler.EnqueueRequestForOwner{OwnerType: &clusterv1.Machine{}}); err != nil { + if err := r.externalTracker.Watch(log, obj, handler.EnqueueRequestForOwner(r.Client.Scheme(), r.Client.RESTMapper(), &clusterv1.Machine{})); err != nil { return external.ReconcileOutput{}, err } diff --git a/internal/controllers/machine/machine_controller_test.go b/internal/controllers/machine/machine_controller_test.go index 4464f21f66cc..ad84ecf5f640 100644 --- a/internal/controllers/machine/machine_controller_test.go +++ b/internal/controllers/machine/machine_controller_test.go @@ -554,7 +554,7 @@ func TestMachineOwnerReference(t *testing.T) { machineValidCluster, machineValidMachine, machineValidControlled, - ).Build() + ).WithStatusSubresource(&clusterv1.Machine{}).Build() mr := &Reconciler{ Client: c, APIReader: c, @@ -724,7 +724,7 @@ func TestReconcileRequest(t *testing.T) { &tc.machine, builder.GenericInfrastructureMachineCRD.DeepCopy(), &infraConfig, - ).WithIndex(&corev1.Node{}, index.NodeProviderIDField, index.NodeByProviderID).Build() + ).WithStatusSubresource(&clusterv1.Machine{}).WithIndex(&corev1.Node{}, index.NodeProviderIDField, index.NodeByProviderID).Build() r := &Reconciler{ Client: clientFake, @@ -971,6 +971,7 @@ func TestMachineConditions(t *testing.T) { node, ). WithIndex(&corev1.Node{}, index.NodeProviderIDField, index.NodeByProviderID). + WithStatusSubresource(&clusterv1.Machine{}). Build() r := &Reconciler{ @@ -1106,7 +1107,7 @@ func TestRemoveMachineFinalizerAfterDeleteReconcile(t *testing.T) { } key := client.ObjectKey{Namespace: m.Namespace, Name: m.Name} mr := &Reconciler{ - Client: fake.NewClientBuilder().WithObjects(testCluster, m).Build(), + Client: fake.NewClientBuilder().WithObjects(testCluster, m).WithStatusSubresource(&clusterv1.Machine{}).Build(), } _, err := mr.Reconcile(ctx, reconcile.Request{NamespacedName: key}) g.Expect(err).ToNot(HaveOccurred()) @@ -1500,6 +1501,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) { Name: "test-cluster", Namespace: metav1.NamespaceDefault, DeletionTimestamp: &deletionts, + Finalizers: []string{clusterv1.ClusterFinalizer}, }, }, machine: &clusterv1.Machine{}, @@ -1641,6 +1643,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) { mcpBeingDeleted.SetName("test-cluster-2") mcpBeingDeleted.SetNamespace("test-cluster") mcpBeingDeleted.SetDeletionTimestamp(&metav1.Time{Time: time.Now()}) + mcpBeingDeleted.SetFinalizers([]string{"block-deletion"}) empBeingDeleted := &unstructured.Unstructured{ Object: map[string]interface{}{ @@ -1654,6 +1657,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) { empBeingDeleted.SetName("test-cluster-3") empBeingDeleted.SetNamespace("test-cluster") empBeingDeleted.SetDeletionTimestamp(&metav1.Time{Time: time.Now()}) + empBeingDeleted.SetFinalizers([]string{"block-deletion"}) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -1980,7 +1984,7 @@ func TestNodeToMachine(t *testing.T) { Client: env, } for _, node := range fakeNodes { - request := r.nodeToMachine(node) + request := r.nodeToMachine(ctx, node) g.Expect(request).To(BeEquivalentTo([]reconcile.Request{ { NamespacedName: client.ObjectKeyFromObject(expectedMachine), @@ -2087,6 +2091,7 @@ func TestNodeDeletion(t *testing.T) { createFakeClient: func(initObjs ...client.Object) client.Client { return fake.NewClientBuilder(). WithObjects(initObjs...). + WithStatusSubresource(&clusterv1.Machine{}). Build() }, }, @@ -2098,6 +2103,7 @@ func TestNodeDeletion(t *testing.T) { createFakeClient: func(initObjs ...client.Object) client.Client { fc := fake.NewClientBuilder(). WithObjects(initObjs...). + WithStatusSubresource(&clusterv1.Machine{}). Build() return fakeClientWithNodeDeletionErr{fc} }, @@ -2110,6 +2116,7 @@ func TestNodeDeletion(t *testing.T) { createFakeClient: func(initObjs ...client.Object) client.Client { fc := fake.NewClientBuilder(). WithObjects(initObjs...). + WithStatusSubresource(&clusterv1.Machine{}). Build() return fakeClientWithNodeDeletionErr{fc} }, @@ -2122,6 +2129,7 @@ func TestNodeDeletion(t *testing.T) { createFakeClient: func(initObjs ...client.Object) client.Client { fc := fake.NewClientBuilder(). WithObjects(initObjs...). + WithStatusSubresource(&clusterv1.Machine{}). Build() return fakeClientWithNodeDeletionErr{fc} }, @@ -2135,6 +2143,7 @@ func TestNodeDeletion(t *testing.T) { createFakeClient: func(initObjs ...client.Object) client.Client { fc := fake.NewClientBuilder(). WithObjects(initObjs...). + WithStatusSubresource(&clusterv1.Machine{}). Build() return fakeClientWithNodeDeletionErr{fc} }, diff --git a/internal/controllers/machinedeployment/machinedeployment_controller.go b/internal/controllers/machinedeployment/machinedeployment_controller.go index ce19faef945f..3273b2f26073 100644 --- a/internal/controllers/machinedeployment/machinedeployment_controller.go +++ b/internal/controllers/machinedeployment/machinedeployment_controller.go @@ -34,7 +34,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/external" @@ -84,13 +83,13 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt For(&clusterv1.MachineDeployment{}). Owns(&clusterv1.MachineSet{}). Watches( - &source.Kind{Type: &clusterv1.MachineSet{}}, + &clusterv1.MachineSet{}, handler.EnqueueRequestsFromMapFunc(r.MachineSetToDeployments), ). WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(clusterToMachineDeployments), builder.WithPredicates( // TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources? @@ -381,7 +380,7 @@ func (r *Reconciler) getMachineDeploymentsForMachineSet(ctx context.Context, ms // MachineSetToDeployments is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation // for MachineDeployments that might adopt an orphaned MachineSet. -func (r *Reconciler) MachineSetToDeployments(o client.Object) []ctrl.Request { +func (r *Reconciler) MachineSetToDeployments(ctx context.Context, o client.Object) []ctrl.Request { result := []ctrl.Request{} ms, ok := o.(*clusterv1.MachineSet) @@ -397,7 +396,7 @@ func (r *Reconciler) MachineSetToDeployments(o client.Object) []ctrl.Request { } } - mds := r.getMachineDeploymentsForMachineSet(context.TODO(), ms) + mds := r.getMachineDeploymentsForMachineSet(ctx, ms) if len(mds) == 0 { return nil } diff --git a/internal/controllers/machinedeployment/machinedeployment_controller_test.go b/internal/controllers/machinedeployment/machinedeployment_controller_test.go index 351c6959fecc..401012a7da70 100644 --- a/internal/controllers/machinedeployment/machinedeployment_controller_test.go +++ b/internal/controllers/machinedeployment/machinedeployment_controller_test.go @@ -735,7 +735,7 @@ func TestMachineSetToDeployments(t *testing.T) { } for _, tc := range testsCases { - got := r.MachineSetToDeployments(tc.mapObject) + got := r.MachineSetToDeployments(ctx, tc.mapObject) g.Expect(got).To(Equal(tc.expected)) } } diff --git a/internal/controllers/machinedeployment/machinedeployment_sync.go b/internal/controllers/machinedeployment/machinedeployment_sync.go index 8f3383bc9802..546ecd85f86f 100644 --- a/internal/controllers/machinedeployment/machinedeployment_sync.go +++ b/internal/controllers/machinedeployment/machinedeployment_sync.go @@ -189,7 +189,7 @@ func (r *Reconciler) createMachineSetAndWait(ctx context.Context, deployment *cl // the MachineDeployment to reconcile with an outdated list of MachineSets which could lead to unwanted creation of // a duplicate MachineSet. var pollErrors []error - if err := wait.PollImmediate(100*time.Millisecond, 10*time.Second, func() (bool, error) { + if err := wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, 10*time.Second, true, func(ctx context.Context) (bool, error) { ms := &clusterv1.MachineSet{} if err := r.Client.Get(ctx, client.ObjectKeyFromObject(newMS), ms); err != nil { // Do not return error here. Continue to poll even if we hit an error diff --git a/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go b/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go index 53448b7e50ae..f485b7e5c0b0 100644 --- a/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go +++ b/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go @@ -41,7 +41,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/api/v1beta1/index" @@ -89,13 +88,13 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt c, err := ctrl.NewControllerManagedBy(mgr). For(&clusterv1.MachineHealthCheck{}). Watches( - &source.Kind{Type: &clusterv1.Machine{}}, + &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(r.machineToMachineHealthCheck), ). WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(r.clusterToMachineHealthCheck), builder.WithPredicates( // TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources? @@ -457,7 +456,7 @@ func (r *Reconciler) patchUnhealthyTargets(ctx context.Context, logger logr.Logg // clusterToMachineHealthCheck maps events from Cluster objects to // MachineHealthCheck objects that belong to the Cluster. -func (r *Reconciler) clusterToMachineHealthCheck(o client.Object) []reconcile.Request { +func (r *Reconciler) clusterToMachineHealthCheck(ctx context.Context, o client.Object) []reconcile.Request { c, ok := o.(*clusterv1.Cluster) if !ok { panic(fmt.Sprintf("Expected a Cluster, got %T", o)) @@ -465,7 +464,7 @@ func (r *Reconciler) clusterToMachineHealthCheck(o client.Object) []reconcile.Re mhcList := &clusterv1.MachineHealthCheckList{} if err := r.Client.List( - context.TODO(), + ctx, mhcList, client.InNamespace(c.Namespace), client.MatchingLabels{clusterv1.ClusterNameLabel: c.Name}, @@ -484,7 +483,7 @@ func (r *Reconciler) clusterToMachineHealthCheck(o client.Object) []reconcile.Re // machineToMachineHealthCheck maps events from Machine objects to // MachineHealthCheck objects that monitor the given machine. -func (r *Reconciler) machineToMachineHealthCheck(o client.Object) []reconcile.Request { +func (r *Reconciler) machineToMachineHealthCheck(ctx context.Context, o client.Object) []reconcile.Request { m, ok := o.(*clusterv1.Machine) if !ok { panic(fmt.Sprintf("Expected a Machine, got %T", o)) @@ -492,7 +491,7 @@ func (r *Reconciler) machineToMachineHealthCheck(o client.Object) []reconcile.Re mhcList := &clusterv1.MachineHealthCheckList{} if err := r.Client.List( - context.TODO(), + ctx, mhcList, client.InNamespace(m.Namespace), client.MatchingLabels{clusterv1.ClusterNameLabel: m.Spec.ClusterName}, @@ -511,18 +510,18 @@ func (r *Reconciler) machineToMachineHealthCheck(o client.Object) []reconcile.Re return requests } -func (r *Reconciler) nodeToMachineHealthCheck(o client.Object) []reconcile.Request { +func (r *Reconciler) nodeToMachineHealthCheck(ctx context.Context, o client.Object) []reconcile.Request { node, ok := o.(*corev1.Node) if !ok { panic(fmt.Sprintf("Expected a corev1.Node, got %T", o)) } - machine, err := getMachineFromNode(context.TODO(), r.Client, node.Name) + machine, err := getMachineFromNode(ctx, r.Client, node.Name) if machine == nil || err != nil { return nil } - return r.machineToMachineHealthCheck(machine) + return r.machineToMachineHealthCheck(ctx, machine) } func (r *Reconciler) watchClusterNodes(ctx context.Context, cluster *clusterv1.Cluster) error { diff --git a/internal/controllers/machinehealthcheck/machinehealthcheck_controller_test.go b/internal/controllers/machinehealthcheck/machinehealthcheck_controller_test.go index 20a37d42aff5..612ddcd1419d 100644 --- a/internal/controllers/machinehealthcheck/machinehealthcheck_controller_test.go +++ b/internal/controllers/machinehealthcheck/machinehealthcheck_controller_test.go @@ -1876,7 +1876,7 @@ func TestClusterToMachineHealthCheck(t *testing.T) { gs.Eventually(getObj).Should(Succeed()) } - got := r.clusterToMachineHealthCheck(tc.object) + got := r.clusterToMachineHealthCheck(ctx, tc.object) gs.Expect(got).To(ConsistOf(tc.expected)) }) } @@ -1951,7 +1951,7 @@ func TestMachineToMachineHealthCheck(t *testing.T) { gs.Eventually(getObj).Should(Succeed()) } - got := r.machineToMachineHealthCheck(tc.object) + got := r.machineToMachineHealthCheck(ctx, tc.object) gs.Expect(got).To(ConsistOf(tc.expected)) }) } @@ -1960,6 +1960,7 @@ func TestMachineToMachineHealthCheck(t *testing.T) { func TestNodeToMachineHealthCheck(t *testing.T) { fakeClient := fake.NewClientBuilder(). WithIndex(&clusterv1.Machine{}, index.MachineNodeNameField, index.MachineByNodeName). + WithStatusSubresource(&clusterv1.MachineHealthCheck{}, &clusterv1.Machine{}). Build() r := &Reconciler{ @@ -2078,7 +2079,7 @@ func TestNodeToMachineHealthCheck(t *testing.T) { gs.Eventually(checkStatus).Should(Equal(o.Status)) } - got := r.nodeToMachineHealthCheck(tc.object) + got := r.nodeToMachineHealthCheck(ctx, tc.object) gs.Expect(got).To(ConsistOf(tc.expected)) }) } @@ -2592,7 +2593,7 @@ func TestPatchTargets(t *testing.T) { machine1, machine2, mhc, - ).Build() + ).WithStatusSubresource(&clusterv1.MachineHealthCheck{}, &clusterv1.Machine{}).Build() r := &Reconciler{ Client: cl, recorder: record.NewFakeRecorder(32), diff --git a/internal/controllers/machineset/machineset_controller.go b/internal/controllers/machineset/machineset_controller.go index fef33c14fce3..035009ce544c 100644 --- a/internal/controllers/machineset/machineset_controller.go +++ b/internal/controllers/machineset/machineset_controller.go @@ -29,6 +29,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" kerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/storage/names" "k8s.io/client-go/tools/record" "k8s.io/klog/v2" @@ -37,7 +38,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/external" @@ -100,13 +100,13 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt For(&clusterv1.MachineSet{}). Owns(&clusterv1.Machine{}). Watches( - &source.Kind{Type: &clusterv1.Machine{}}, + &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(r.MachineToMachineSets), ). WithOptions(options). WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(clusterToMachineSets), builder.WithPredicates( // TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources? @@ -728,7 +728,7 @@ func (r *Reconciler) waitForMachineCreation(ctx context.Context, machineList []* for i := 0; i < len(machineList); i++ { machine := machineList[i] - pollErr := util.PollImmediate(stateConfirmationInterval, stateConfirmationTimeout, func() (bool, error) { + pollErr := wait.PollUntilContextTimeout(ctx, stateConfirmationInterval, stateConfirmationTimeout, true, func(ctx context.Context) (bool, error) { key := client.ObjectKey{Namespace: machine.Namespace, Name: machine.Name} if err := r.Client.Get(ctx, key, &clusterv1.Machine{}); err != nil { if apierrors.IsNotFound(err) { @@ -754,7 +754,7 @@ func (r *Reconciler) waitForMachineDeletion(ctx context.Context, machineList []* for i := 0; i < len(machineList); i++ { machine := machineList[i] - pollErr := util.PollImmediate(stateConfirmationInterval, stateConfirmationTimeout, func() (bool, error) { + pollErr := wait.PollUntilContextTimeout(ctx, stateConfirmationInterval, stateConfirmationTimeout, true, func(ctx context.Context) (bool, error) { m := &clusterv1.Machine{} key := client.ObjectKey{Namespace: machine.Namespace, Name: machine.Name} err := r.Client.Get(ctx, key, m) @@ -774,7 +774,7 @@ func (r *Reconciler) waitForMachineDeletion(ctx context.Context, machineList []* // MachineToMachineSets is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation // for MachineSets that might adopt an orphaned Machine. -func (r *Reconciler) MachineToMachineSets(o client.Object) []ctrl.Request { +func (r *Reconciler) MachineToMachineSets(ctx context.Context, o client.Object) []ctrl.Request { result := []ctrl.Request{} m, ok := o.(*clusterv1.Machine) @@ -782,8 +782,6 @@ func (r *Reconciler) MachineToMachineSets(o client.Object) []ctrl.Request { panic(fmt.Sprintf("Expected a Machine but got a %T", o)) } - // This won't log unless the global logger is set - ctx := context.Background() log := ctrl.LoggerFrom(ctx, "Machine", klog.KObj(m)) // Check if the controller reference is already set and diff --git a/internal/controllers/machineset/machineset_controller_test.go b/internal/controllers/machineset/machineset_controller_test.go index 01e55825ecd0..e4519dd89f45 100644 --- a/internal/controllers/machineset/machineset_controller_test.go +++ b/internal/controllers/machineset/machineset_controller_test.go @@ -468,7 +468,7 @@ func TestMachineSetOwnerReference(t *testing.T) { ms1, ms2, ms3, - ).Build(), + ).WithStatusSubresource(&clusterv1.MachineSet{}).Build(), recorder: record.NewFakeRecorder(32), } @@ -505,6 +505,7 @@ func TestMachineSetReconcile(t *testing.T) { Name: "machineset1", Namespace: metav1.NamespaceDefault, DeletionTimestamp: &dt, + Finalizers: []string{"block-deletion"}, }, Spec: clusterv1.MachineSetSpec{ ClusterName: testClusterName, @@ -515,7 +516,7 @@ func TestMachineSetReconcile(t *testing.T) { } msr := &Reconciler{ - Client: fake.NewClientBuilder().WithObjects(testCluster, ms).Build(), + Client: fake.NewClientBuilder().WithObjects(testCluster, ms).WithStatusSubresource(&clusterv1.MachineSet{}).Build(), recorder: record.NewFakeRecorder(32), } result, err := msr.Reconcile(ctx, request) @@ -537,7 +538,7 @@ func TestMachineSetReconcile(t *testing.T) { rec := record.NewFakeRecorder(32) msr := &Reconciler{ - Client: fake.NewClientBuilder().WithObjects(testCluster, ms).Build(), + Client: fake.NewClientBuilder().WithObjects(testCluster, ms).WithStatusSubresource(&clusterv1.MachineSet{}).Build(), recorder: rec, } _, _ = msr.Reconcile(ctx, request) @@ -558,7 +559,7 @@ func TestMachineSetReconcile(t *testing.T) { rec := record.NewFakeRecorder(32) msr := &Reconciler{ - Client: fake.NewClientBuilder().WithObjects(testCluster, ms).Build(), + Client: fake.NewClientBuilder().WithObjects(testCluster, ms).WithStatusSubresource(&clusterv1.MachineSet{}).Build(), recorder: rec, } _, err := msr.Reconcile(ctx, request) @@ -651,7 +652,7 @@ func TestMachineSetToMachines(t *testing.T) { t.Run(tc.name, func(t *testing.T) { gs := NewWithT(t) - got := r.MachineToMachineSets(tc.mapObject) + got := r.MachineToMachineSets(ctx, tc.mapObject) gs.Expect(got).To(Equal(tc.expected)) }) } @@ -879,7 +880,7 @@ func TestMachineSetReconcile_MachinesCreatedConditionFalseOnBadInfraRef(t *testi request := reconcile.Request{ NamespacedName: key, } - fakeClient := fake.NewClientBuilder().WithObjects(cluster, ms, builder.GenericInfrastructureMachineTemplateCRD.DeepCopy()).Build() + fakeClient := fake.NewClientBuilder().WithObjects(cluster, ms, builder.GenericInfrastructureMachineTemplateCRD.DeepCopy()).WithStatusSubresource(&clusterv1.MachineSet{}).Build() msr := &Reconciler{ Client: fakeClient, diff --git a/internal/controllers/topology/cluster/cluster_controller.go b/internal/controllers/topology/cluster/cluster_controller.go index 5e8898ef92ae..36bba2862226 100644 --- a/internal/controllers/topology/cluster/cluster_controller.go +++ b/internal/controllers/topology/cluster/cluster_controller.go @@ -32,7 +32,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/api/v1beta1/index" @@ -95,11 +94,11 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt )). Named("topology/cluster"). Watches( - &source.Kind{Type: &clusterv1.ClusterClass{}}, + &clusterv1.ClusterClass{}, handler.EnqueueRequestsFromMapFunc(r.clusterClassToCluster), ). Watches( - &source.Kind{Type: &clusterv1.MachineDeployment{}}, + &clusterv1.MachineDeployment{}, handler.EnqueueRequestsFromMapFunc(r.machineDeploymentToCluster), // Only trigger Cluster reconciliation if the MachineDeployment is topology owned. builder.WithPredicates(predicates.ResourceIsTopologyOwned(ctrl.LoggerFrom(ctx))), @@ -114,6 +113,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt r.externalTracker = external.ObjectTracker{ Controller: c, + Cache: mgr.GetCache(), } r.patchEngine = patches.NewEngine(r.RuntimeClient) r.recorder = mgr.GetEventRecorderFor("topology/cluster") @@ -280,7 +280,7 @@ func (r *Reconciler) reconcile(ctx context.Context, s *scope.Scope) (ctrl.Result func (r *Reconciler) setupDynamicWatches(ctx context.Context, s *scope.Scope) error { if s.Current.InfrastructureCluster != nil { if err := r.externalTracker.Watch(ctrl.LoggerFrom(ctx), s.Current.InfrastructureCluster, - &handler.EnqueueRequestForOwner{OwnerType: &clusterv1.Cluster{}}, + handler.EnqueueRequestForOwner(r.Client.Scheme(), r.Client.RESTMapper(), &clusterv1.Cluster{}), // Only trigger Cluster reconciliation if the InfrastructureCluster is topology owned. predicates.ResourceIsTopologyOwned(ctrl.LoggerFrom(ctx))); err != nil { return errors.Wrap(err, "error watching Infrastructure CR") @@ -288,7 +288,7 @@ func (r *Reconciler) setupDynamicWatches(ctx context.Context, s *scope.Scope) er } if s.Current.ControlPlane.Object != nil { if err := r.externalTracker.Watch(ctrl.LoggerFrom(ctx), s.Current.ControlPlane.Object, - &handler.EnqueueRequestForOwner{OwnerType: &clusterv1.Cluster{}}, + handler.EnqueueRequestForOwner(r.Client.Scheme(), r.Client.RESTMapper(), &clusterv1.Cluster{}), // Only trigger Cluster reconciliation if the ControlPlane is topology owned. predicates.ResourceIsTopologyOwned(ctrl.LoggerFrom(ctx))); err != nil { return errors.Wrap(err, "error watching ControlPlane CR") @@ -320,7 +320,7 @@ func (r *Reconciler) callBeforeClusterCreateHook(ctx context.Context, s *scope.S // clusterClassToCluster is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation // for Cluster to update when its own ClusterClass gets updated. -func (r *Reconciler) clusterClassToCluster(o client.Object) []ctrl.Request { +func (r *Reconciler) clusterClassToCluster(ctx context.Context, o client.Object) []ctrl.Request { clusterClass, ok := o.(*clusterv1.ClusterClass) if !ok { panic(fmt.Sprintf("Expected a ClusterClass but got a %T", o)) @@ -328,7 +328,7 @@ func (r *Reconciler) clusterClassToCluster(o client.Object) []ctrl.Request { clusterList := &clusterv1.ClusterList{} if err := r.Client.List( - context.TODO(), + ctx, clusterList, client.MatchingFields{index.ClusterClassNameField: clusterClass.Name}, client.InNamespace(clusterClass.Namespace), @@ -347,7 +347,7 @@ func (r *Reconciler) clusterClassToCluster(o client.Object) []ctrl.Request { // machineDeploymentToCluster is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation // for Cluster to update when one of its own MachineDeployments gets updated. -func (r *Reconciler) machineDeploymentToCluster(o client.Object) []ctrl.Request { +func (r *Reconciler) machineDeploymentToCluster(_ context.Context, o client.Object) []ctrl.Request { md, ok := o.(*clusterv1.MachineDeployment) if !ok { panic(fmt.Sprintf("Expected a MachineDeployment but got a %T", o)) diff --git a/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper_test.go b/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper_test.go index 251b9acb432c..57d41ce25f5d 100644 --- a/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper_test.go +++ b/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper_test.go @@ -785,7 +785,7 @@ func TestServerSideApplyWithDefaulting(t *testing.T) { // It also calculates and returns the corresponding MutatingWebhookConfiguration. // Note: To activate the webhook, the MutatingWebhookConfiguration has to be deployed. func setupWebhookWithManager(ns *corev1.Namespace) (*KubeadmConfigTemplateTestDefaulter, *admissionv1.MutatingWebhookConfiguration, error) { - webhookServer := env.Manager.GetWebhookServer() + webhookServer := env.Manager.GetWebhookServer().(*webhook.DefaultServer) // Calculate webhook host and path. // Note: This is done the same way as in our envtest package. @@ -799,10 +799,10 @@ func setupWebhookWithManager(ns *corev1.Namespace) (*KubeadmConfigTemplateTestDe // Note: This should only ever be called once with the same path, otherwise we get a panic. defaulter := &KubeadmConfigTemplateTestDefaulter{} webhookServer.Register(webhookPath, - admission.WithCustomDefaulter(&bootstrapv1.KubeadmConfigTemplate{}, defaulter)) + admission.WithCustomDefaulter(env.Manager.GetScheme(), &bootstrapv1.KubeadmConfigTemplate{}, defaulter)) // Calculate the MutatingWebhookConfiguration - caBundle, err := os.ReadFile(filepath.Join(webhookServer.CertDir, webhookServer.CertName)) + caBundle, err := os.ReadFile(filepath.Join(webhookServer.Options.CertDir, webhookServer.Options.CertName)) if err != nil { return nil, nil, err } @@ -816,7 +816,7 @@ func setupWebhookWithManager(ns *corev1.Namespace) (*KubeadmConfigTemplateTestDe { Name: ns.Name + ".kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io", ClientConfig: admissionv1.WebhookClientConfig{ - URL: pointer.String(fmt.Sprintf("https://%s%s", net.JoinHostPort(webhookHost, strconv.Itoa(webhookServer.Port)), webhookPath)), + URL: pointer.String(fmt.Sprintf("https://%s%s", net.JoinHostPort(webhookHost, strconv.Itoa(webhookServer.Options.Port)), webhookPath)), CABundle: caBundle, }, Rules: []admissionv1.RuleWithOperations{ diff --git a/internal/controllers/topology/cluster/suite_test.go b/internal/controllers/topology/cluster/suite_test.go index fec64edd3b35..5befa6a1a5f8 100644 --- a/internal/controllers/topology/cluster/suite_test.go +++ b/internal/controllers/topology/cluster/suite_test.go @@ -60,16 +60,12 @@ func TestMain(m *testing.M) { } } setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { - unstructuredCachingClient, err := client.NewDelegatingClient( - client.NewDelegatingClientInput{ - // Use the default client for write operations. - Client: mgr.GetClient(), - // For read operations, use the same cache used by all the controllers but ensure - // unstructured objects will be also cached (this does not happen with the default client). - CacheReader: mgr.GetCache(), - CacheUnstructured: true, + unstructuredCachingClient, err := client.New(mgr.GetConfig(), client.Options{ + Cache: &client.CacheOptions{ + Reader: mgr.GetCache(), + Unstructured: true, }, - ) + }) if err != nil { panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err)) } diff --git a/internal/controllers/topology/machinedeployment/machinedeployment_controller_test.go b/internal/controllers/topology/machinedeployment/machinedeployment_controller_test.go index 1dea7d7e0e53..9f88b27b2bd5 100644 --- a/internal/controllers/topology/machinedeployment/machinedeployment_controller_test.go +++ b/internal/controllers/topology/machinedeployment/machinedeployment_controller_test.go @@ -46,18 +46,14 @@ func TestMachineDeploymentTopologyFinalizer(t *testing.T) { md := mdBuilder.Build() mdWithFinalizer := mdBuilder.Build() mdWithFinalizer.Finalizers = []string{clusterv1.MachineDeploymentTopologyFinalizer} - mdWithDeletionTimestamp := mdBuilder.Build() - deletionTimestamp := metav1.Now() - mdWithDeletionTimestamp.DeletionTimestamp = &deletionTimestamp - - mdWithDeletionTimestampAndFinalizer := mdWithDeletionTimestamp.DeepCopy() - mdWithDeletionTimestampAndFinalizer.Finalizers = []string{clusterv1.MachineDeploymentTopologyFinalizer} testCases := []struct { name string md *clusterv1.MachineDeployment expectFinalizer bool }{ + // Note: We are not testing the case of a MD with deletionTimestamp and no finalizer. + // This case is impossible to reproduce in fake client without deleting the object. { name: "should add ClusterTopology finalizer to a MachineDeployment with no finalizer", md: md, @@ -68,11 +64,6 @@ func TestMachineDeploymentTopologyFinalizer(t *testing.T) { md: mdWithFinalizer, expectFinalizer: true, }, - { - name: "should not add ClusterTopology finalizer on MachineDeployment with Deletion Timestamp and no finalizer ", - md: mdWithDeletionTimestamp, - expectFinalizer: false, - }, } for _, tc := range testCases { @@ -117,10 +108,14 @@ func TestMachineDeploymentReconciler_ReconcileDelete(t *testing.T) { Build() mhc := builder.MachineHealthCheck(metav1.NamespaceDefault, "md").Build() md.SetDeletionTimestamp(&deletionTimeStamp) + md.SetFinalizers([]string{clusterv1.MachineDeploymentTopologyFinalizer}) t.Run("Should delete templates of a MachineDeployment", func(t *testing.T) { g := NewWithT(t) + // Copying the MD so changes made by reconcileDelete do not affect other tests. + md := md.DeepCopy() + fakeClient := fake.NewClientBuilder(). WithScheme(fakeScheme). WithObjects(md, mdBT, mdIMT). @@ -133,10 +128,7 @@ func TestMachineDeploymentReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, md) g.Expect(err).ToNot(HaveOccurred()) - afterMD := &clusterv1.MachineDeployment{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(md), afterMD)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMD, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(md, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, mdBT)).To(BeFalse()) g.Expect(templateExists(fakeClient, mdIMT)).To(BeFalse()) }) @@ -149,6 +141,7 @@ func TestMachineDeploymentReconciler_ReconcileDelete(t *testing.T) { WithInfrastructureTemplate(mdWithoutBootstrapTemplateIMT). Build() mdWithoutBootstrapTemplate.SetDeletionTimestamp(&deletionTimeStamp) + mdWithoutBootstrapTemplate.SetFinalizers([]string{clusterv1.MachineDeploymentTopologyFinalizer}) fakeClient := fake.NewClientBuilder(). WithScheme(fakeScheme). @@ -162,16 +155,16 @@ func TestMachineDeploymentReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, mdWithoutBootstrapTemplate) g.Expect(err).ToNot(HaveOccurred()) - afterMD := &clusterv1.MachineDeployment{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(mdWithoutBootstrapTemplate), afterMD)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMD, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(mdWithoutBootstrapTemplate, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, mdWithoutBootstrapTemplateIMT)).To(BeFalse()) }) t.Run("Should not delete templates of a MachineDeployment when they are still in use in a MachineSet", func(t *testing.T) { g := NewWithT(t) + // Copying the MD so changes made by reconcileDelete do not affect other tests. + md := md.DeepCopy() + ms := builder.MachineSet(md.Namespace, "md"). WithBootstrapTemplate(mdBT). WithInfrastructureTemplate(mdIMT). @@ -192,16 +185,16 @@ func TestMachineDeploymentReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, md) g.Expect(err).ToNot(HaveOccurred()) - afterMD := &clusterv1.MachineDeployment{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(md), afterMD)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMD, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(md, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, mdBT)).To(BeTrue()) g.Expect(templateExists(fakeClient, mdIMT)).To(BeTrue()) }) t.Run("Should delete a MachineHealthCheck when its linked MachineDeployment is deleted", func(t *testing.T) { g := NewWithT(t) + // Copying the MD so changes made by reconcileDelete do not affect other tests. + md := md.DeepCopy() + fakeClient := fake.NewClientBuilder(). WithScheme(fakeScheme). WithObjects(md, mhc). @@ -214,6 +207,8 @@ func TestMachineDeploymentReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, md) g.Expect(err).ToNot(HaveOccurred()) + g.Expect(controllerutil.ContainsFinalizer(md, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse()) + gotMHC := clusterv1.MachineHealthCheck{} err = fakeClient.Get(ctx, client.ObjectKeyFromObject(mhc), &gotMHC) g.Expect(apierrors.IsNotFound(err)).To(BeTrue()) diff --git a/internal/controllers/topology/machineset/machineset_controller_test.go b/internal/controllers/topology/machineset/machineset_controller_test.go index bd790eb49a47..7ab2fa308acd 100644 --- a/internal/controllers/topology/machineset/machineset_controller_test.go +++ b/internal/controllers/topology/machineset/machineset_controller_test.go @@ -60,18 +60,14 @@ func TestMachineSetTopologyFinalizer(t *testing.T) { ms := msBuilder.Build() msWithFinalizer := msBuilder.Build() msWithFinalizer.Finalizers = []string{clusterv1.MachineSetTopologyFinalizer} - msWithDeletionTimestamp := msBuilder.Build() - deletionTimestamp := metav1.Now() - msWithDeletionTimestamp.DeletionTimestamp = &deletionTimestamp - - msWithDeletionTimestampAndFinalizer := msWithDeletionTimestamp.DeepCopy() - msWithDeletionTimestampAndFinalizer.Finalizers = []string{clusterv1.MachineSetTopologyFinalizer} testCases := []struct { name string ms *clusterv1.MachineSet expectFinalizer bool }{ + // Note: We are not testing the case of a MS with deletionTimestamp and no finalizer. + // This case is impossible to reproduce in fake client without deleting the object. { name: "should add ClusterTopology finalizer to a MachineSet with no finalizer", ms: ms, @@ -82,11 +78,6 @@ func TestMachineSetTopologyFinalizer(t *testing.T) { ms: msWithFinalizer, expectFinalizer: true, }, - { - name: "should not add ClusterTopology finalizer on MachineSet with Deletion Timestamp and no finalizer ", - ms: msWithDeletionTimestamp, - expectFinalizer: false, - }, } for _, tc := range testCases { @@ -135,6 +126,7 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { }). Build() ms.SetDeletionTimestamp(&deletionTimeStamp) + ms.SetFinalizers([]string{clusterv1.MachineSetTopologyFinalizer}) ms.SetOwnerReferences([]metav1.OwnerReference{ { Kind: "MachineDeployment", @@ -146,6 +138,9 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { t.Run("Should delete templates of a MachineSet", func(t *testing.T) { g := NewWithT(t) + // Copying the MS so changes made by reconcileDelete do not affect other tests. + ms := ms.DeepCopy() + fakeClient := fake.NewClientBuilder(). WithScheme(fakeScheme). WithObjects(ms, msBT, msIMT). @@ -158,10 +153,7 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, ms) g.Expect(err).ToNot(HaveOccurred()) - afterMS := &clusterv1.MachineSet{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ms), afterMS)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMS, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(ms, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, msBT)).To(BeFalse()) g.Expect(templateExists(fakeClient, msIMT)).To(BeFalse()) }) @@ -177,6 +169,7 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { }). Build() msWithoutBootstrapTemplate.SetDeletionTimestamp(&deletionTimeStamp) + msWithoutBootstrapTemplate.SetFinalizers([]string{clusterv1.MachineSetTopologyFinalizer}) msWithoutBootstrapTemplate.SetOwnerReferences([]metav1.OwnerReference{ { Kind: "MachineDeployment", @@ -197,16 +190,16 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, msWithoutBootstrapTemplate) g.Expect(err).ToNot(HaveOccurred()) - afterMS := &clusterv1.MachineSet{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(msWithoutBootstrapTemplate), afterMS)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMS, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(msWithoutBootstrapTemplate, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, msWithoutBootstrapTemplateIMT)).To(BeFalse()) }) t.Run("Should not delete templates of a MachineSet when they are still in use in a MachineDeployment", func(t *testing.T) { g := NewWithT(t) + // Copying the MS so changes made by reconcileDelete do not affect other tests. + ms := ms.DeepCopy() + md := builder.MachineDeployment(metav1.NamespaceDefault, "md"). WithBootstrapTemplate(msBT). WithInfrastructureTemplate(msIMT). @@ -224,10 +217,7 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, ms) g.Expect(err).ToNot(HaveOccurred()) - afterMS := &clusterv1.MachineSet{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ms), afterMS)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMS, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(ms, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, msBT)).To(BeTrue()) g.Expect(templateExists(fakeClient, msIMT)).To(BeTrue()) }) @@ -240,6 +230,7 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { WithInfrastructureTemplate(msIMT). Build() md.SetDeletionTimestamp(&deletionTimeStamp) + md.SetFinalizers([]string{clusterv1.MachineDeploymentTopologyFinalizer}) // anotherMS is another MachineSet of the same MachineDeployment using the same templates. // Because anotherMS is not in deleting, reconcileDelete should not delete the templates. @@ -270,10 +261,7 @@ func TestMachineSetReconciler_ReconcileDelete(t *testing.T) { _, err := r.reconcileDelete(ctx, ms) g.Expect(err).ToNot(HaveOccurred()) - afterMS := &clusterv1.MachineSet{} - g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ms), afterMS)).To(Succeed()) - - g.Expect(controllerutil.ContainsFinalizer(afterMS, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) + g.Expect(controllerutil.ContainsFinalizer(ms, clusterv1.MachineSetTopologyFinalizer)).To(BeFalse()) g.Expect(templateExists(fakeClient, msBT)).To(BeTrue()) g.Expect(templateExists(fakeClient, msIMT)).To(BeTrue()) }) diff --git a/internal/goproxy/goproxy.go b/internal/goproxy/goproxy.go index d79958a27771..a44bd0ce194c 100644 --- a/internal/goproxy/goproxy.go +++ b/internal/goproxy/goproxy.go @@ -81,7 +81,7 @@ func (g *Client) GetVersions(ctx context.Context, gomodulePath string) (semver.V var rawResponse []byte var responseStatusCode int var retryError error - _ = wait.PollImmediateWithContext(ctx, retryableOperationInterval, retryableOperationTimeout, func(ctx context.Context) (bool, error) { + _ = wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) { retryError = nil resp, err := http.DefaultClient.Do(req) diff --git a/internal/test/envtest/environment.go b/internal/test/envtest/environment.go index 38d62a356179..a3dbb2e7f932 100644 --- a/internal/test/envtest/environment.go +++ b/internal/test/envtest/environment.go @@ -35,7 +35,6 @@ import ( corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -46,9 +45,9 @@ import ( "k8s.io/klog/v2/klogr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/webhook" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" @@ -251,15 +250,20 @@ func newEnvironment(uncachedObjs ...client.Object) *Environment { } options := manager.Options{ - Scheme: scheme.Scheme, - MetricsBindAddress: "0", - CertDir: env.WebhookInstallOptions.LocalServingCertDir, - Port: env.WebhookInstallOptions.LocalServingPort, - ClientDisableCacheFor: objs, - Host: host, - MapperProvider: func(c *rest.Config) (meta.RESTMapper, error) { - return apiutil.NewDynamicRESTMapper(c, apiutil.WithExperimentalLazyMapper) + Scheme: scheme.Scheme, + MetricsBindAddress: "0", + Client: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: objs, + }, }, + WebhookServer: webhook.NewServer( + webhook.Options{ + Port: env.WebhookInstallOptions.LocalServingPort, + CertDir: env.WebhookInstallOptions.LocalServingCertDir, + Host: host, + }, + ), } mgr, err := ctrl.NewManager(env.Config, options) diff --git a/internal/webhooks/cluster.go b/internal/webhooks/cluster.go index 92815b3dcbb6..7d22bcf8942c 100644 --- a/internal/webhooks/cluster.go +++ b/internal/webhooks/cluster.go @@ -30,15 +30,16 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apimachinery/pkg/util/wait" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/internal/topology/check" "sigs.k8s.io/cluster-api/internal/topology/variables" - "sigs.k8s.io/cluster-api/util" "sigs.k8s.io/cluster-api/util/conditions" "sigs.k8s.io/cluster-api/util/version" ) @@ -110,33 +111,33 @@ func (webhook *Cluster) Default(ctx context.Context, obj runtime.Object) error { } // ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type. -func (webhook *Cluster) ValidateCreate(ctx context.Context, obj runtime.Object) error { +func (webhook *Cluster) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { cluster, ok := obj.(*clusterv1.Cluster) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a Cluster but got a %T", obj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Cluster but got a %T", obj)) } return webhook.validate(ctx, nil, cluster) } // ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type. -func (webhook *Cluster) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error { +func (webhook *Cluster) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { newCluster, ok := newObj.(*clusterv1.Cluster) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a Cluster but got a %T", newObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Cluster but got a %T", newObj)) } oldCluster, ok := oldObj.(*clusterv1.Cluster) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a Cluster but got a %T", oldObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Cluster but got a %T", oldObj)) } return webhook.validate(ctx, oldCluster, newCluster) } // ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type. -func (webhook *Cluster) ValidateDelete(_ context.Context, _ runtime.Object) error { - return nil +func (webhook *Cluster) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil } -func (webhook *Cluster) validate(ctx context.Context, oldCluster, newCluster *clusterv1.Cluster) error { +func (webhook *Cluster) validate(ctx context.Context, oldCluster, newCluster *clusterv1.Cluster) (admission.Warnings, error) { var allErrs field.ErrorList // The Cluster name is used as a label value. This check ensures that names which are not valid label values are rejected. if errs := validation.IsValidLabelValue(newCluster.Name); len(errs) != 0 { @@ -205,9 +206,9 @@ func (webhook *Cluster) validate(ctx context.Context, oldCluster, newCluster *cl } if len(allErrs) > 0 { - return apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Cluster").GroupKind(), newCluster.Name, allErrs) + return nil, apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Cluster").GroupKind(), newCluster.Name, allErrs) } - return nil + return nil, nil } func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newCluster *clusterv1.Cluster, fldPath *field.Path) field.ErrorList { @@ -555,7 +556,7 @@ func (webhook *Cluster) pollClusterClassForCluster(ctx context.Context, cluster clusterClass := &clusterv1.ClusterClass{} var clusterClassPollErr error // TODO: Add a webhook warning if the ClusterClass is not up to date or not found. - _ = util.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) { + _ = wait.PollUntilContextTimeout(ctx, 200*time.Millisecond, 2*time.Second, true, func(ctx context.Context) (bool, error) { if clusterClassPollErr = webhook.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: cluster.Spec.Topology.Class}, clusterClass); clusterClassPollErr != nil { return false, nil //nolint:nilerr } diff --git a/internal/webhooks/cluster_test.go b/internal/webhooks/cluster_test.go index a9efcd6dedff..9f0874509c5f 100644 --- a/internal/webhooks/cluster_test.go +++ b/internal/webhooks/cluster_test.go @@ -1004,7 +1004,7 @@ func TestClusterValidation(t *testing.T) { // Create the webhook. webhook := &Cluster{} - err := webhook.validate(ctx, tt.old, tt.in) + _, err := webhook.validate(ctx, tt.old, tt.in) if tt.expectErr { g.Expect(err).To(HaveOccurred()) return @@ -1268,7 +1268,7 @@ func TestClusterTopologyValidation(t *testing.T) { // Create the webhook and add the fakeClient as its client. This is required because the test uses a Managed Topology. webhook := &Cluster{Client: fakeClient} - err := webhook.validate(ctx, tt.old, tt.in) + _, err := webhook.validate(ctx, tt.old, tt.in) if tt.expectErr { g.Expect(err).To(HaveOccurred()) return @@ -1549,10 +1549,11 @@ func TestClusterTopologyValidationWithClient(t *testing.T) { c := &Cluster{Client: fakeClient} // Checks the return error. + _, err := c.ValidateCreate(ctx, tt.cluster) if tt.wantErr { - g.Expect(c.ValidateCreate(ctx, tt.cluster)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(c.ValidateCreate(ctx, tt.cluster)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -1970,10 +1971,11 @@ func TestClusterTopologyValidationForTopologyClassChange(t *testing.T) { secondCluster.Spec.Topology.Class = tt.secondClass.Name // Checks the return error. + _, err := c.ValidateUpdate(ctx, cluster, secondCluster) if tt.wantErr { - g.Expect(c.ValidateUpdate(ctx, cluster, secondCluster)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(c.ValidateUpdate(ctx, cluster, secondCluster)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -2091,10 +2093,11 @@ func TestMovingBetweenManagedAndUnmanaged(t *testing.T) { updatedCluster.Spec.Topology = tt.updatedTopology // Checks the return error. + _, err := c.ValidateUpdate(ctx, tt.cluster, updatedCluster) if tt.wantErr { - g.Expect(c.ValidateUpdate(ctx, tt.cluster, updatedCluster)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(c.ValidateUpdate(ctx, tt.cluster, updatedCluster)).To(Succeed()) + g.Expect(err).NotTo(HaveOccurred()) } }) } @@ -2214,10 +2217,11 @@ func TestClusterClassPollingErrors(t *testing.T) { Build()} // Checks the return error. + _, err := c.validate(ctx, tt.oldCluster, tt.cluster) if tt.wantErr { - g.Expect(c.validate(ctx, tt.oldCluster, tt.cluster)).NotTo(Succeed()) + g.Expect(err).To(HaveOccurred()) } else { - g.Expect(c.validate(ctx, tt.oldCluster, tt.cluster)).To(Succeed()) + g.Expect(err).ToNot(HaveOccurred()) } }) } diff --git a/internal/webhooks/clusterclass.go b/internal/webhooks/clusterclass.go index b5ccb3e77c2d..a90fa33fb595 100644 --- a/internal/webhooks/clusterclass.go +++ b/internal/webhooks/clusterclass.go @@ -31,6 +31,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/api/v1beta1/index" @@ -86,45 +87,45 @@ func defaultNamespace(ref *corev1.ObjectReference, namespace string) { } // ValidateCreate implements validation for ClusterClass create. -func (webhook *ClusterClass) ValidateCreate(ctx context.Context, obj runtime.Object) error { +func (webhook *ClusterClass) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { in, ok := obj.(*clusterv1.ClusterClass) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", obj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", obj)) } - return webhook.validate(ctx, nil, in) + return nil, webhook.validate(ctx, nil, in) } // ValidateUpdate implements validation for ClusterClass update. -func (webhook *ClusterClass) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error { +func (webhook *ClusterClass) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { newClusterClass, ok := newObj.(*clusterv1.ClusterClass) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", newObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", newObj)) } oldClusterClass, ok := oldObj.(*clusterv1.ClusterClass) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", oldObj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", oldObj)) } - return webhook.validate(ctx, oldClusterClass, newClusterClass) + return nil, webhook.validate(ctx, oldClusterClass, newClusterClass) } // ValidateDelete implements validation for ClusterClass delete. -func (webhook *ClusterClass) ValidateDelete(ctx context.Context, obj runtime.Object) error { +func (webhook *ClusterClass) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { clusterClass, ok := obj.(*clusterv1.ClusterClass) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", obj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterClass but got a %T", obj)) } clusters, err := webhook.getClustersUsingClusterClass(ctx, clusterClass) if err != nil { - return apierrors.NewInternalError(errors.Wrapf(err, "could not retrieve Clusters using ClusterClass")) + return nil, apierrors.NewInternalError(errors.Wrapf(err, "could not retrieve Clusters using ClusterClass")) } if len(clusters) > 0 { // TODO(killianmuldoon): Improve error here to include the names of some clusters using the clusterClass. - return apierrors.NewForbidden(clusterv1.GroupVersion.WithResource("ClusterClass").GroupResource(), clusterClass.Name, + return nil, apierrors.NewForbidden(clusterv1.GroupVersion.WithResource("ClusterClass").GroupResource(), clusterClass.Name, fmt.Errorf("ClusterClass cannot be deleted because it is used by %d Cluster(s)", len(clusters))) } - return nil + return nil, nil } func (webhook *ClusterClass) validate(ctx context.Context, oldClusterClass, newClusterClass *clusterv1.ClusterClass) error { diff --git a/internal/webhooks/runtime/extensionconfig_webhook.go b/internal/webhooks/runtime/extensionconfig_webhook.go index 1f852fea09e9..6ebcca3aaf41 100644 --- a/internal/webhooks/runtime/extensionconfig_webhook.go +++ b/internal/webhooks/runtime/extensionconfig_webhook.go @@ -30,6 +30,7 @@ import ( "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1" "sigs.k8s.io/cluster-api/feature" @@ -71,33 +72,33 @@ func (webhook *ExtensionConfig) Default(_ context.Context, obj runtime.Object) e } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (webhook *ExtensionConfig) ValidateCreate(ctx context.Context, obj runtime.Object) error { +func (webhook *ExtensionConfig) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { extensionConfig, ok := obj.(*runtimev1.ExtensionConfig) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an ExtensionConfig but got a %T", obj)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an ExtensionConfig but got a %T", obj)) } return webhook.validate(ctx, nil, extensionConfig) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (webhook *ExtensionConfig) ValidateUpdate(ctx context.Context, old, updated runtime.Object) error { +func (webhook *ExtensionConfig) ValidateUpdate(ctx context.Context, old, updated runtime.Object) (admission.Warnings, error) { oldExtensionConfig, ok := old.(*runtimev1.ExtensionConfig) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an ExtensionConfig but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an ExtensionConfig but got a %T", old)) } newExtensionConfig, ok := updated.(*runtimev1.ExtensionConfig) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected an ExtensionConfig but got a %T", updated)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an ExtensionConfig but got a %T", updated)) } return webhook.validate(ctx, oldExtensionConfig, newExtensionConfig) } // validate validates an ExtensionConfig create or update. -func (webhook *ExtensionConfig) validate(_ context.Context, _, newExtensionConfig *runtimev1.ExtensionConfig) error { +func (webhook *ExtensionConfig) validate(_ context.Context, _, newExtensionConfig *runtimev1.ExtensionConfig) (admission.Warnings, error) { // NOTE: ExtensionConfig is behind the RuntimeSDK feature gate flag; the web hook // must prevent creating and updating objects in case the feature flag is disabled. if !feature.Gates.Enabled(feature.RuntimeSDK) { - return field.Forbidden( + return nil, field.Forbidden( field.NewPath("spec"), "can be set only if the RuntimeSDK feature flag is enabled", ) @@ -115,14 +116,14 @@ func (webhook *ExtensionConfig) validate(_ context.Context, _, newExtensionConfi allErrs = append(allErrs, validateExtensionConfigSpec(newExtensionConfig)...) if len(allErrs) > 0 { - return apierrors.NewInvalid(runtimev1.GroupVersion.WithKind("ExtensionConfig").GroupKind(), newExtensionConfig.Name, allErrs) + return nil, apierrors.NewInvalid(runtimev1.GroupVersion.WithKind("ExtensionConfig").GroupKind(), newExtensionConfig.Name, allErrs) } - return nil + return nil, nil } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (webhook *ExtensionConfig) ValidateDelete(_ context.Context, _ runtime.Object) error { - return nil +func (webhook *ExtensionConfig) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil } func validateExtensionConfigSpec(e *runtimev1.ExtensionConfig) field.ErrorList { diff --git a/internal/webhooks/runtime/extensionconfig_webhook_test.go b/internal/webhooks/runtime/extensionconfig_webhook_test.go index 1fa477cfaefc..f0536aaf91e6 100644 --- a/internal/webhooks/runtime/extensionconfig_webhook_test.go +++ b/internal/webhooks/runtime/extensionconfig_webhook_test.go @@ -95,7 +95,7 @@ func TestExtensionConfigValidationFeatureGated(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.RuntimeSDK, tt.featureGate)() webhook := ExtensionConfig{} g := NewWithT(t) - err := webhook.validate(context.TODO(), tt.old, tt.new) + _, err := webhook.validate(context.TODO(), tt.old, tt.new) if tt.expectErr { g.Expect(err).To(HaveOccurred()) return @@ -340,7 +340,7 @@ func TestExtensionConfigValidate(t *testing.T) { g.Expect(webhook.Default(ctx, tt.old)).To(Succeed()) } - err := webhook.validate(ctx, tt.old, tt.in) + _, err := webhook.validate(ctx, tt.old, tt.in) if tt.expectErr { g.Expect(err).To(HaveOccurred()) return diff --git a/internal/webhooks/test/suite_test.go b/internal/webhooks/test/suite_test.go index e7571b37d5d0..25fc42d150ef 100644 --- a/internal/webhooks/test/suite_test.go +++ b/internal/webhooks/test/suite_test.go @@ -48,16 +48,12 @@ func TestMain(m *testing.M) { } } setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { - unstructuredCachingClient, err := client.NewDelegatingClient( - client.NewDelegatingClientInput{ - // Use the default client for write operations. - Client: mgr.GetClient(), - // For read operations, use the same cache used by all the controllers but ensure - // unstructured objects will be also cached (this does not happen with the default client). - CacheReader: mgr.GetCache(), - CacheUnstructured: true, + unstructuredCachingClient, err := client.New(mgr.GetConfig(), client.Options{ + Cache: &client.CacheOptions{ + Reader: mgr.GetCache(), + Unstructured: true, }, - ) + }) if err != nil { panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err)) } diff --git a/internal/webhooks/util/util.go b/internal/webhooks/util/util.go index cd3c6f2ee89a..856c07f66843 100644 --- a/internal/webhooks/util/util.go +++ b/internal/webhooks/util/util.go @@ -48,18 +48,21 @@ func CustomDefaultValidateTest(ctx context.Context, obj runtime.Object, webhook t.Run("validate-on-create", func(t *testing.T) { g := gomega.NewWithT(t) g.Expect(webhook.Default(ctx, createCopy)).To(gomega.Succeed()) - g.Expect(webhook.ValidateCreate(ctx, createCopy)).To(gomega.Succeed()) + _, err := webhook.ValidateCreate(ctx, createCopy) + g.Expect(err).ToNot(gomega.HaveOccurred()) }) t.Run("validate-on-update", func(t *testing.T) { g := gomega.NewWithT(t) g.Expect(webhook.Default(ctx, defaultingUpdateCopy)).To(gomega.Succeed()) g.Expect(webhook.Default(ctx, updateCopy)).To(gomega.Succeed()) - g.Expect(webhook.ValidateUpdate(ctx, createCopy, defaultingUpdateCopy)).To(gomega.Succeed()) + _, err := webhook.ValidateUpdate(ctx, createCopy, defaultingUpdateCopy) + g.Expect(err).ToNot(gomega.HaveOccurred()) }) t.Run("validate-on-delete", func(t *testing.T) { g := gomega.NewWithT(t) g.Expect(webhook.Default(ctx, deleteCopy)).To(gomega.Succeed()) - g.Expect(webhook.ValidateDelete(ctx, deleteCopy)).To(gomega.Succeed()) + _, err := webhook.ValidateDelete(ctx, deleteCopy) + g.Expect(err).ToNot(gomega.HaveOccurred()) }) } } diff --git a/main.go b/main.go index 1efcb3aec716..7f1e4f363329 100644 --- a/main.go +++ b/main.go @@ -21,8 +21,6 @@ import ( "context" "flag" "fmt" - "net/http" - _ "net/http/pprof" "os" "time" @@ -30,10 +28,8 @@ import ( "github.com/spf13/pflag" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection/resourcelock" cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/logs" @@ -41,9 +37,10 @@ import ( _ "k8s.io/component-base/logs/json/register" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/webhook" clusterv1alpha3 "sigs.k8s.io/cluster-api/api/v1alpha3" clusterv1alpha4 "sigs.k8s.io/cluster-api/api/v1alpha4" @@ -228,16 +225,6 @@ func main() { // klog.Background will automatically use the right logger. ctrl.SetLogger(klog.Background()) - if profilerAddress != "" { - setupLog.Info(fmt.Sprintf("Profiler listening for requests at %s", profilerAddress)) - go func() { - srv := http.Server{Addr: profilerAddress, ReadHeaderTimeout: 2 * time.Second} - if err := srv.ListenAndServe(); err != nil { - setupLog.Error(err, "problem running profiler server") - } - }() - } - restConfig := ctrl.GetConfigOrDie() restConfig.QPS = restConfigQPS restConfig.Burst = restConfigBurst @@ -259,6 +246,11 @@ func main() { os.Exit(1) } + var watchNamespaces []string + if watchNamespace != "" { + watchNamespaces = []string{watchNamespace} + } + ctrlOptions := ctrl.Options{ Scheme: scheme, MetricsBindAddress: metricsBindAddr, @@ -268,22 +260,27 @@ func main() { RenewDeadline: &leaderElectionRenewDeadline, RetryPeriod: &leaderElectionRetryPeriod, LeaderElectionResourceLock: resourcelock.LeasesResourceLock, - Namespace: watchNamespace, - SyncPeriod: &syncPeriod, - ClientDisableCacheFor: []client.Object{ - &corev1.ConfigMap{}, - &corev1.Secret{}, + HealthProbeBindAddress: healthAddr, + PprofBindAddress: profilerAddress, + Cache: cache.Options{ + Namespaces: watchNamespaces, + SyncPeriod: &syncPeriod, }, - Port: webhookPort, - CertDir: webhookCertDir, - HealthProbeBindAddress: healthAddr, - TLSOpts: tlsOptionOverrides, - } - - if feature.Gates.Enabled(feature.LazyRestmapper) { - ctrlOptions.MapperProvider = func(c *rest.Config) (meta.RESTMapper, error) { - return apiutil.NewDynamicRESTMapper(c, apiutil.WithExperimentalLazyMapper) - } + Client: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: []client.Object{ + &corev1.ConfigMap{}, + &corev1.Secret{}, + }, + }, + }, + WebhookServer: webhook.NewServer( + webhook.Options{ + Port: webhookPort, + CertDir: webhookCertDir, + TLSOpts: tlsOptionOverrides, + }, + ), } mgr, err := ctrl.NewManager(restConfig, ctrlOptions) @@ -362,16 +359,13 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager) { } if feature.Gates.Enabled(feature.ClusterTopology) { - unstructuredCachingClient, err := client.NewDelegatingClient( - client.NewDelegatingClientInput{ - // Use the default client for write operations. - Client: mgr.GetClient(), - // For read operations, use the same cache used by all the controllers but ensure - // unstructured objects will be also cached (this does not happen with the default client). - CacheReader: mgr.GetCache(), - CacheUnstructured: true, + unstructuredCachingClient, err := client.New(mgr.GetConfig(), client.Options{ + HTTPClient: mgr.GetHTTPClient(), + Cache: &client.CacheOptions{ + Reader: mgr.GetCache(), + Unstructured: true, }, - ) + }) if err != nil { setupLog.Error(err, "unable to create unstructured caching client", "controller", "ClusterTopology") os.Exit(1) diff --git a/test/e2e/config/docker.yaml b/test/e2e/config/docker.yaml index 102ecefdbded..c66c62bbfbfd 100644 --- a/test/e2e/config/docker.yaml +++ b/test/e2e/config/docker.yaml @@ -281,7 +281,6 @@ variables: EXP_MACHINE_POOL: "true" CLUSTER_TOPOLOGY: "true" EXP_RUNTIME_SDK: "true" - EXP_LAZY_RESTMAPPER: "true" intervals: default/wait-controllers: ["3m", "10s"] diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index d5bf3d59c4c4..5b727c92a3ab 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -32,6 +32,7 @@ import ( . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -98,6 +99,8 @@ func init() { func TestE2E(t *testing.T) { g := NewWithT(t) + ctrl.SetLogger(klog.Background()) + // If running in prow, make sure to use the artifacts folder that will be reported in test grid (ignoring the value provided by flag). if prowArtifactFolder, exists := os.LookupEnv("ARTIFACTS"); exists { artifactFolder = prowArtifactFolder diff --git a/test/extension/main.go b/test/extension/main.go index 4fd74f198f9e..9d64f9711113 100644 --- a/test/extension/main.go +++ b/test/extension/main.go @@ -123,6 +123,7 @@ func main() { ctrl.SetLogger(klog.Background()) // Initialize the golang profiler server, if required. + // TODO(sbueringer): remove this once we switched to using a manager. if profilerAddress != "" { setupLog.Info(fmt.Sprintf("Profiler listening for requests at %s", profilerAddress)) go func() { diff --git a/test/framework/cluster_proxy.go b/test/framework/cluster_proxy.go index 67d6c59c2823..1b690c9497ff 100644 --- a/test/framework/cluster_proxy.go +++ b/test/framework/cluster_proxy.go @@ -194,7 +194,7 @@ func (p *clusterProxy) GetClient() client.Client { var c client.Client var newClientErr error - err := wait.PollImmediate(retryableOperationInterval, retryableOperationTimeout, func() (bool, error) { + err := wait.PollUntilContextTimeout(context.TODO(), retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) { c, newClientErr = client.New(config, client.Options{Scheme: p.scheme}) if newClientErr != nil { return false, nil //nolint:nilerr diff --git a/test/framework/deployment_helpers.go b/test/framework/deployment_helpers.go index 8115a3297a99..0b73368ad38e 100644 --- a/test/framework/deployment_helpers.go +++ b/test/framework/deployment_helpers.go @@ -224,7 +224,7 @@ func newWatchPodLogsEventHandler(ctx context.Context, input watchPodLogsInput, s } } -func (eh *watchPodLogsEventHandler) OnAdd(obj interface{}) { +func (eh *watchPodLogsEventHandler) OnAdd(obj interface{}, _ bool) { pod := obj.(*corev1.Pod) eh.streamPodLogs(pod) } @@ -287,7 +287,7 @@ func (eh *watchPodLogsEventHandler) streamPodLogs(pod *corev1.Pod) { } // Retry streaming the logs of the pods unless ctx.Done() or if the pod does not exist anymore. - err = wait.PollInfiniteWithContext(eh.ctx, 2*time.Second, func(ctx context.Context) (done bool, err error) { + err = wait.PollUntilContextCancel(eh.ctx, 2*time.Second, false, func(ctx context.Context) (done bool, err error) { // Wait for pod to be in running state actual, err := eh.input.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{}) if err != nil { diff --git a/test/framework/machinepool_helpers.go b/test/framework/machinepool_helpers.go index 0735917e1513..b1c26303c33b 100644 --- a/test/framework/machinepool_helpers.go +++ b/test/framework/machinepool_helpers.go @@ -286,7 +286,7 @@ func getMachinePoolInstanceVersions(ctx context.Context, input GetMachinesPoolIn versions := make([]string, len(instances)) for i, instance := range instances { node := &corev1.Node{} - err := wait.PollImmediate(retryableOperationInterval, retryableOperationTimeout, func() (bool, error) { + err := wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) { err := input.WorkloadClusterGetter.Get(ctx, client.ObjectKey{Name: instance.Name}, node) if err != nil { return false, nil //nolint:nilerr diff --git a/test/go.mod b/test/go.mod index 7cdbabe3b65b..5146cdcc13be 100644 --- a/test/go.mod +++ b/test/go.mod @@ -15,15 +15,15 @@ require ( github.com/pkg/errors v0.9.1 github.com/spf13/pflag v1.0.5 github.com/vincent-petithory/dataurl v1.0.0 - k8s.io/api v0.26.1 - k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.1 - k8s.io/client-go v0.26.1 - k8s.io/component-base v0.26.1 - k8s.io/klog/v2 v2.80.1 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 + k8s.io/api v0.27.2 + k8s.io/apiextensions-apiserver v0.27.2 + k8s.io/apimachinery v0.27.2 + k8s.io/client-go v0.27.2 + k8s.io/component-base v0.27.2 + k8s.io/klog/v2 v2.90.1 + k8s.io/utils v0.0.0-20230209194617-a36077c30491 sigs.k8s.io/cluster-api v0.0.0-00010101000000-000000000000 - sigs.k8s.io/controller-runtime v0.14.6 + sigs.k8s.io/controller-runtime v0.15.0 sigs.k8s.io/kind v0.19.0 sigs.k8s.io/yaml v1.3.0 ) @@ -53,9 +53,9 @@ require ( github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/zapr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobuffalo/flect v1.0.2 // indirect @@ -68,7 +68,7 @@ require ( github.com/google/go-github/v48 v48.2.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -93,11 +93,11 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/prometheus/client_golang v1.15.1 // indirect - github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cobra v1.7.0 // indirect @@ -125,9 +125,10 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiserver v0.26.1 // indirect - k8s.io/cluster-bootstrap v0.25.0 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + gotest.tools/v3 v3.4.0 // indirect + k8s.io/apiserver v0.27.2 // indirect + k8s.io/cluster-bootstrap v0.27.2 // indirect + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/test/go.sum b/test/go.sum index 9fe337181dba..353b470ab5ec 100644 --- a/test/go.sum +++ b/test/go.sum @@ -109,6 +109,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -156,17 +157,14 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -249,8 +247,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI= github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg= @@ -318,16 +316,16 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -355,7 +353,7 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= 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= @@ -401,8 +399,8 @@ github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= @@ -415,7 +413,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -428,8 +426,8 @@ github.com/sigma/bdoor v0.0.0-20160202064022-babf2a4017b0/go.mod h1:WBu7REWbxC/s github.com/sigma/vmw-guestinfo v0.0.0-20160204083807-95dd4126d6e8/go.mod h1:JrRFFC0veyh0cibh0DAhriSY7/gV3kDdNaVUOmfx01U= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -490,6 +488,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -503,14 +502,13 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org v0.0.0-20160314031811-03efcb870d84/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= @@ -559,6 +557,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -624,6 +623,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -671,6 +671,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -716,7 +717,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -752,6 +752,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= @@ -868,6 +869,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -890,7 +892,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/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= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -898,33 +901,33 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= -k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= -k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= -k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -k8s.io/cluster-bootstrap v0.25.0 h1:KJ2/r0dV+bLfTK5EBobAVKvjGel3N4Qqh3bvnzh9qPk= -k8s.io/cluster-bootstrap v0.25.0/go.mod h1:x/TCtY3EiuR/rODkA3SvVQT3uSssQLf9cXcmSjdDTe0= -k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= -k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= +k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= +k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= +k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= +k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= +k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= +k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= +k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= +k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/cluster-bootstrap v0.27.2 h1:OL3onrOwrUD7NQxBUqQwTl1Uu2GQKCkw9BMHpc4PbiA= +k8s.io/cluster-bootstrap v0.27.2/go.mod h1:b++PF0mjUOiTKdPQFlDw7p4V2VquANZ8SfhAwzxZJFM= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= +k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= -sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.19.0 h1:ZSUh6/kpab6fiowT6EqL4k8xSbedI2NWxyuUOtoPFe4= sigs.k8s.io/kind v0.19.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= diff --git a/test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go b/test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go index 97c4af588691..f748fc56cc3a 100644 --- a/test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go +++ b/test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go @@ -22,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) func (c *DockerCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { @@ -44,21 +45,21 @@ func (c *DockerCluster) Default() { var _ webhook.Validator = &DockerCluster{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (c *DockerCluster) ValidateCreate() error { +func (c *DockerCluster) ValidateCreate() (admission.Warnings, error) { if allErrs := validateDockerClusterSpec(c.Spec); len(allErrs) > 0 { - return apierrors.NewInvalid(GroupVersion.WithKind("DockerCluster").GroupKind(), c.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerCluster").GroupKind(), c.Name, allErrs) } - return nil + return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (c *DockerCluster) ValidateUpdate(_ runtime.Object) error { - return nil +func (c *DockerCluster) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { + return nil, nil } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (c *DockerCluster) ValidateDelete() error { - return nil +func (c *DockerCluster) ValidateDelete() (admission.Warnings, error) { + return nil, nil } func defaultDockerClusterSpec(s *DockerClusterSpec) { diff --git a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go b/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go index 1ad6af6b9844..46451cb0221c 100644 --- a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go +++ b/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/cluster-api/feature" ) @@ -51,11 +52,11 @@ func (r *DockerClusterTemplate) Default() { var _ webhook.Validator = &DockerClusterTemplate{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *DockerClusterTemplate) ValidateCreate() error { +func (r *DockerClusterTemplate) ValidateCreate() (admission.Warnings, error) { // NOTE: DockerClusterTemplate is behind ClusterTopology feature gate flag; the web hook // must prevent creating new objects in case the feature flag is disabled. if !feature.Gates.Enabled(feature.ClusterTopology) { - return field.Forbidden( + return nil, field.Forbidden( field.NewPath("spec"), "can be set only if the ClusterTopology feature flag is enabled", ) @@ -63,28 +64,28 @@ func (r *DockerClusterTemplate) ValidateCreate() error { allErrs := validateDockerClusterSpec(r.Spec.Template.Spec) if len(allErrs) > 0 { - return apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), r.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), r.Name, allErrs) } - return nil + return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *DockerClusterTemplate) ValidateUpdate(oldRaw runtime.Object) error { +func (r *DockerClusterTemplate) ValidateUpdate(oldRaw runtime.Object) (admission.Warnings, error) { var allErrs field.ErrorList old, ok := oldRaw.(*DockerClusterTemplate) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a DockerClusterTemplate but got a %T", oldRaw)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerClusterTemplate but got a %T", oldRaw)) } if !reflect.DeepEqual(r.Spec.Template.Spec, old.Spec.Template.Spec) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), r, dockerClusterTemplateImmutableMsg)) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), r.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *DockerClusterTemplate) ValidateDelete() error { - return nil +func (r *DockerClusterTemplate) ValidateDelete() (admission.Warnings, error) { + return nil, nil } diff --git a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go b/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go index d32279166f4a..95e38aecba59 100644 --- a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go +++ b/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go @@ -42,7 +42,8 @@ func TestDockerClusterTemplateValidationFeatureGateEnabled(t *testing.T) { }, }, } - g.Expect(dct.ValidateCreate()).To(Succeed()) + _, err := dct.ValidateCreate() + g.Expect(err).NotTo(HaveOccurred()) }) } @@ -61,6 +62,7 @@ func TestDockerClusterTemplateValidationFeatureGateDisabled(t *testing.T) { }, }, } - g.Expect(dct.ValidateCreate()).NotTo(Succeed()) + _, err := dct.ValidateCreate() + g.Expect(err).To(HaveOccurred()) }) } diff --git a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go b/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go index adbbb231c4d7..d7df886f80db 100644 --- a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go +++ b/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go @@ -49,24 +49,24 @@ type DockerMachineTemplateWebhook struct{} var _ webhook.CustomValidator = &DockerMachineTemplateWebhook{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (*DockerMachineTemplateWebhook) ValidateCreate(_ context.Context, _ runtime.Object) error { - return nil +func (*DockerMachineTemplateWebhook) ValidateCreate(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (*DockerMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw runtime.Object, newRaw runtime.Object) error { +func (*DockerMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw runtime.Object, newRaw runtime.Object) (admission.Warnings, error) { newObj, ok := newRaw.(*DockerMachineTemplate) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", newRaw)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", newRaw)) } oldObj, ok := oldRaw.(*DockerMachineTemplate) if !ok { - return apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", oldRaw)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", oldRaw)) } req, err := admission.RequestFromContext(ctx) if err != nil { - return apierrors.NewBadRequest(fmt.Sprintf("expected a admission.Request inside context: %v", err)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a admission.Request inside context: %v", err)) } var allErrs field.ErrorList @@ -75,12 +75,12 @@ func (*DockerMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), newObj, dockerMachineTemplateImmutableMsg)) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid(GroupVersion.WithKind("DockerMachineTemplate").GroupKind(), newObj.Name, allErrs) + return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerMachineTemplate").GroupKind(), newObj.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (*DockerMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) error { - return nil +func (*DockerMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil } diff --git a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go b/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go index 2d54f8c3a61b..0e5d6422d3f8 100644 --- a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go +++ b/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go @@ -91,7 +91,7 @@ func TestDockerMachineTemplateInvalid(t *testing.T) { if tt.req != nil { ctx = admission.NewContextWithRequest(ctx, *tt.req) } - err := wh.ValidateUpdate(ctx, tt.oldTemplate, tt.newTemplate) + _, err := wh.ValidateUpdate(ctx, tt.oldTemplate, tt.newTemplate) if (err != nil) != tt.wantError { t.Errorf("unexpected result - wanted %+v, got %+v", tt.wantError, err) } diff --git a/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go b/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go index ae4e090b9612..631cea187f02 100644 --- a/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go +++ b/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go @@ -33,7 +33,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/remote" @@ -151,12 +150,12 @@ func (r *DockerMachinePoolReconciler) SetupWithManager(ctx context.Context, mgr WithOptions(options). WithEventFilter(predicates.ResourceNotPaused(ctrl.LoggerFrom(ctx))). Watches( - &source.Kind{Type: &expv1.MachinePool{}}, + &expv1.MachinePool{}, handler.EnqueueRequestsFromMapFunc(utilexp.MachinePoolToInfrastructureMapFunc( infraexpv1.GroupVersion.WithKind("DockerMachinePool"), ctrl.LoggerFrom(ctx))), ). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(clusterToDockerMachinePools), builder.WithPredicates( predicates.ClusterUnpausedAndInfrastructureReady(ctrl.LoggerFrom(ctx)), diff --git a/test/infrastructure/docker/internal/controllers/dockercluster_controller.go b/test/infrastructure/docker/internal/controllers/dockercluster_controller.go index 8c8602b8935a..94c65fa5f405 100644 --- a/test/infrastructure/docker/internal/controllers/dockercluster_controller.go +++ b/test/infrastructure/docker/internal/controllers/dockercluster_controller.go @@ -29,7 +29,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/infrastructure/container" @@ -199,7 +198,7 @@ func (r *DockerClusterReconciler) SetupWithManager(ctx context.Context, mgr ctrl WithOptions(options). WithEventFilter(predicates.ResourceNotPaused(ctrl.LoggerFrom(ctx))). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(util.ClusterToInfrastructureMapFunc(ctx, infrav1.GroupVersion.WithKind("DockerCluster"), mgr.GetClient(), &infrav1.DockerCluster{})), builder.WithPredicates( predicates.ClusterUnpaused(ctrl.LoggerFrom(ctx)), diff --git a/test/infrastructure/docker/internal/controllers/dockermachine_controller.go b/test/infrastructure/docker/internal/controllers/dockermachine_controller.go index 7e485f3e477b..22d165e744b5 100644 --- a/test/infrastructure/docker/internal/controllers/dockermachine_controller.go +++ b/test/infrastructure/docker/internal/controllers/dockermachine_controller.go @@ -32,7 +32,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" "sigs.k8s.io/kind/pkg/cluster/constants" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -430,15 +429,15 @@ func (r *DockerMachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl WithOptions(options). WithEventFilter(predicates.ResourceNotPaused(ctrl.LoggerFrom(ctx))). Watches( - &source.Kind{Type: &clusterv1.Machine{}}, + &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(util.MachineToInfrastructureMapFunc(infrav1.GroupVersion.WithKind("DockerMachine"))), ). Watches( - &source.Kind{Type: &infrav1.DockerCluster{}}, + &infrav1.DockerCluster{}, handler.EnqueueRequestsFromMapFunc(r.DockerClusterToDockerMachines), ). Watches( - &source.Kind{Type: &clusterv1.Cluster{}}, + &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(clusterToDockerMachines), builder.WithPredicates( predicates.ClusterUnpausedAndInfrastructureReady(ctrl.LoggerFrom(ctx)), @@ -452,14 +451,14 @@ func (r *DockerMachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl // DockerClusterToDockerMachines is a handler.ToRequestsFunc to be used to enqueue // requests for reconciliation of DockerMachines. -func (r *DockerMachineReconciler) DockerClusterToDockerMachines(o client.Object) []ctrl.Request { +func (r *DockerMachineReconciler) DockerClusterToDockerMachines(ctx context.Context, o client.Object) []ctrl.Request { result := []ctrl.Request{} c, ok := o.(*infrav1.DockerCluster) if !ok { panic(fmt.Sprintf("Expected a DockerCluster but got a %T", o)) } - cluster, err := util.GetOwnerCluster(context.TODO(), r.Client, c.ObjectMeta) + cluster, err := util.GetOwnerCluster(ctx, r.Client, c.ObjectMeta) switch { case apierrors.IsNotFound(err) || cluster == nil: return result @@ -469,7 +468,7 @@ func (r *DockerMachineReconciler) DockerClusterToDockerMachines(o client.Object) labels := map[string]string{clusterv1.ClusterNameLabel: cluster.Name} machineList := &clusterv1.MachineList{} - if err := r.Client.List(context.TODO(), machineList, client.InNamespace(c.Namespace), client.MatchingLabels(labels)); err != nil { + if err := r.Client.List(ctx, machineList, client.InNamespace(c.Namespace), client.MatchingLabels(labels)); err != nil { return nil } for _, m := range machineList.Items { diff --git a/test/infrastructure/docker/internal/controllers/dockermachine_controller_test.go b/test/infrastructure/docker/internal/controllers/dockermachine_controller_test.go index d828618f7ba5..e6f92db96367 100644 --- a/test/infrastructure/docker/internal/controllers/dockermachine_controller_test.go +++ b/test/infrastructure/docker/internal/controllers/dockermachine_controller_test.go @@ -17,6 +17,7 @@ limitations under the License. package controllers import ( + "context" "testing" . "github.com/onsi/gomega" @@ -56,7 +57,7 @@ func TestDockerMachineReconciler_DockerClusterToDockerMachines(t *testing.T) { r := DockerMachineReconciler{ Client: c, } - out := r.DockerClusterToDockerMachines(dockerCluster) + out := r.DockerClusterToDockerMachines(context.Background(), dockerCluster) machineNames := make([]string, len(out)) for i := range out { machineNames[i] = out[i].Name diff --git a/test/infrastructure/docker/internal/docker/machine.go b/test/infrastructure/docker/internal/docker/machine.go index 4d1d3511803b..33bf0bc719bf 100644 --- a/test/infrastructure/docker/internal/docker/machine.go +++ b/test/infrastructure/docker/internal/docker/machine.go @@ -255,7 +255,7 @@ func (m *Machine) Create(ctx context.Context, image string, role string, version } // After creating a node we need to wait a small amount of time until crictl does not return an error. // This fixes an issue where we try to kubeadm init too quickly after creating the container. - err = wait.PollImmediate(500*time.Millisecond, 4*time.Second, func() (bool, error) { + err = wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 4*time.Second, true, func(ctx context.Context) (bool, error) { ps := m.container.Commander.Command("crictl", "ps") return ps.Run(ctx) == nil, nil }) diff --git a/test/infrastructure/docker/main.go b/test/infrastructure/docker/main.go index 2b4bb432be46..a3c6891072dc 100644 --- a/test/infrastructure/docker/main.go +++ b/test/infrastructure/docker/main.go @@ -21,17 +21,15 @@ import ( "context" "flag" "fmt" - "net/http" "os" "time" // +kubebuilder:scaffold:imports "github.com/spf13/pflag" - "k8s.io/apimachinery/pkg/api/meta" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/scheme" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection/resourcelock" cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/logs" @@ -39,8 +37,10 @@ import ( _ "k8s.io/component-base/logs/json/register" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/webhook" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/controllers/remote" @@ -55,63 +55,98 @@ import ( infraexpv1alpha4 "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/api/v1alpha4" infraexpv1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/api/v1beta1" expcontrollers "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/controllers" + "sigs.k8s.io/cluster-api/util/flags" + "sigs.k8s.io/cluster-api/version" ) var ( - myscheme = runtime.NewScheme() + scheme = runtime.NewScheme() setupLog = ctrl.Log.WithName("setup") // flags. - metricsBindAddr string - enableLeaderElection bool - profilerAddress string - syncPeriod time.Duration - concurrency int - restConfigQPS float32 - restConfigBurst int - healthAddr string - webhookPort int - webhookCertDir string - logOptions = logs.NewOptions() + metricsBindAddr string + enableLeaderElection bool + leaderElectionLeaseDuration time.Duration + leaderElectionRenewDeadline time.Duration + leaderElectionRetryPeriod time.Duration + watchNamespace string + watchFilterValue string + profilerAddress string + concurrency int + syncPeriod time.Duration + restConfigQPS float32 + restConfigBurst int + webhookPort int + webhookCertDir string + healthAddr string + tlsOptions = flags.TLSOptions{} + logOptions = logs.NewOptions() ) func init() { - _ = scheme.AddToScheme(myscheme) - _ = infrav1alpha3.AddToScheme(myscheme) - _ = infrav1alpha4.AddToScheme(myscheme) - _ = infrav1.AddToScheme(myscheme) - _ = infraexpv1alpha3.AddToScheme(myscheme) - _ = infraexpv1alpha4.AddToScheme(myscheme) - _ = infraexpv1.AddToScheme(myscheme) - _ = clusterv1.AddToScheme(myscheme) - _ = expv1.AddToScheme(myscheme) + _ = clientgoscheme.AddToScheme(scheme) + _ = infrav1alpha3.AddToScheme(scheme) + _ = infrav1alpha4.AddToScheme(scheme) + _ = infrav1.AddToScheme(scheme) + _ = infraexpv1alpha3.AddToScheme(scheme) + _ = infraexpv1alpha4.AddToScheme(scheme) + _ = infraexpv1.AddToScheme(scheme) + _ = clusterv1.AddToScheme(scheme) + _ = expv1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } +// InitFlags initializes the flags. func initFlags(fs *pflag.FlagSet) { logsv1.AddFlags(logOptions, fs) fs.StringVar(&metricsBindAddr, "metrics-bind-addr", "localhost:8080", "The address the metric endpoint binds to.") - fs.IntVar(&concurrency, "concurrency", 10, - "The number of docker machines to process simultaneously") + fs.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") + + fs.DurationVar(&leaderElectionLeaseDuration, "leader-elect-lease-duration", 15*time.Second, + "Interval at which non-leader candidates will wait to force acquire leadership (duration string)") + + fs.DurationVar(&leaderElectionRenewDeadline, "leader-elect-renew-deadline", 10*time.Second, + "Duration that the leading controller manager will retry refreshing leadership before giving up (duration string)") + + fs.DurationVar(&leaderElectionRetryPeriod, "leader-elect-retry-period", 2*time.Second, + "Duration the LeaderElector clients should wait between tries of actions (duration string)") + + fs.StringVar(&watchNamespace, "namespace", "", + "Namespace that the controller watches to reconcile cluster-api objects. If unspecified, the controller watches for cluster-api objects across all namespaces.") + + fs.StringVar(&watchFilterValue, "watch-filter", "", + fmt.Sprintf("Label value that the controller watches to reconcile cluster-api objects. Label key is always %s. If unspecified, the controller watches for all cluster-api objects.", clusterv1.WatchLabel)) + fs.StringVar(&profilerAddress, "profiler-address", "", "Bind address to expose the pprof profiler (e.g. localhost:6060)") + + fs.IntVar(&concurrency, "concurrency", 10, + "The number of docker machines to process simultaneously") + fs.DurationVar(&syncPeriod, "sync-period", 10*time.Minute, "The minimum interval at which watched resources are reconciled (e.g. 15m)") + fs.Float32Var(&restConfigQPS, "kube-api-qps", 20, "Maximum queries per second from the controller client to the Kubernetes API server. Defaults to 20") + fs.IntVar(&restConfigBurst, "kube-api-burst", 30, "Maximum number of queries that should be allowed in one burst from the controller client to the Kubernetes API server. Default 30") - fs.StringVar(&healthAddr, "health-addr", ":9440", - "The address the health endpoint binds to.") + fs.IntVar(&webhookPort, "webhook-port", 9443, "Webhook Server port") + fs.StringVar(&webhookCertDir, "webhook-cert-dir", "/tmp/k8s-webhook-server/serving-certs/", "Webhook cert dir, only used when webhook-port is specified.") + fs.StringVar(&healthAddr, "health-addr", ":9440", + "The address the health endpoint binds to.") + + flags.AddTLSOptions(fs, &tlsOptions) + feature.MutableGates.AddFlag(fs) } @@ -122,8 +157,8 @@ func main() { } initFlags(pflag.CommandLine) - pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() if err := logsv1.ValidateAndApply(logOptions, nil); err != nil { @@ -134,36 +169,52 @@ func main() { // klog.Background will automatically use the right logger. ctrl.SetLogger(klog.Background()) - if profilerAddress != "" { - setupLog.Info(fmt.Sprintf("Profiler listening for requests at %s", profilerAddress)) - go func() { - srv := http.Server{Addr: profilerAddress, ReadHeaderTimeout: 2 * time.Second} - if err := srv.ListenAndServe(); err != nil { - setupLog.Error(err, "problem running profiler server") - } - }() - } - restConfig := ctrl.GetConfigOrDie() restConfig.QPS = restConfigQPS restConfig.Burst = restConfigBurst restConfig.UserAgent = remote.DefaultClusterAPIUserAgent("cluster-api-docker-controller-manager") + + tlsOptionOverrides, err := flags.GetTLSOptionOverrideFuncs(tlsOptions) + if err != nil { + setupLog.Error(err, "unable to add TLS settings to the webhook server") + os.Exit(1) + } + + var watchNamespaces []string + if watchNamespace != "" { + watchNamespaces = []string{watchNamespace} + } + ctrlOptions := ctrl.Options{ - Scheme: myscheme, + Scheme: scheme, MetricsBindAddress: metricsBindAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "controller-leader-election-capd", - SyncPeriod: &syncPeriod, + LeaseDuration: &leaderElectionLeaseDuration, + RenewDeadline: &leaderElectionRenewDeadline, + RetryPeriod: &leaderElectionRetryPeriod, LeaderElectionResourceLock: resourcelock.LeasesResourceLock, HealthProbeBindAddress: healthAddr, - Port: webhookPort, - CertDir: webhookCertDir, - } - - if feature.Gates.Enabled(feature.LazyRestmapper) { - ctrlOptions.MapperProvider = func(c *rest.Config) (meta.RESTMapper, error) { - return apiutil.NewDynamicRESTMapper(c, apiutil.WithExperimentalLazyMapper) - } + PprofBindAddress: profilerAddress, + Cache: cache.Options{ + Namespaces: watchNamespaces, + SyncPeriod: &syncPeriod, + }, + Client: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: []client.Object{ + &corev1.ConfigMap{}, + &corev1.Secret{}, + }, + }, + }, + WebhookServer: webhook.NewServer( + webhook.Options{ + Port: webhookPort, + CertDir: webhookCertDir, + TLSOpts: tlsOptionOverrides, + }, + ), } mgr, err := ctrl.NewManager(restConfig, ctrlOptions) @@ -180,7 +231,7 @@ func main() { setupWebhooks(mgr) // +kubebuilder:scaffold:builder - setupLog.Info("starting manager") + setupLog.Info("starting manager", "version", version.Get().String()) if err := mgr.Start(ctx); err != nil { setupLog.Error(err, "problem running manager") os.Exit(1) diff --git a/util/defaulting/defaulting.go b/util/defaulting/defaulting.go index 8681a95d2ba0..7436dc3ac9f6 100644 --- a/util/defaulting/defaulting.go +++ b/util/defaulting/defaulting.go @@ -45,18 +45,21 @@ func DefaultValidateTest(object DefaultingValidator) func(*testing.T) { t.Run("validate-on-create", func(t *testing.T) { g := NewWithT(t) createCopy.Default() - g.Expect(createCopy.ValidateCreate()).To(Succeed()) + _, err := createCopy.ValidateCreate() + g.Expect(err).ToNot(HaveOccurred()) }) t.Run("validate-on-update", func(t *testing.T) { g := NewWithT(t) defaultingUpdateCopy.Default() updateCopy.Default() - g.Expect(defaultingUpdateCopy.ValidateUpdate(updateCopy)).To(Succeed()) + _, err := defaultingUpdateCopy.ValidateUpdate(updateCopy) + g.Expect(err).ToNot(HaveOccurred()) }) t.Run("validate-on-delete", func(t *testing.T) { g := NewWithT(t) deleteCopy.Default() - g.Expect(deleteCopy.ValidateDelete()).To(Succeed()) + _, err := deleteCopy.ValidateDelete() + g.Expect(err).ToNot(HaveOccurred()) }) } } diff --git a/util/predicates/cluster_predicates.go b/util/predicates/cluster_predicates.go index 19364f145997..1fdfa678f56e 100644 --- a/util/predicates/cluster_predicates.go +++ b/util/predicates/cluster_predicates.go @@ -157,10 +157,8 @@ func ClusterUpdateUnpaused(logger logr.Logger) predicate.Funcs { // Example use: // // err := controller.Watch( -// &source.Kind{Type: &clusterv1.Cluster{}}, -// &handler.EnqueueRequestsFromMapFunc{ -// ToRequests: clusterToMachines, -// }, +// source.Kind(cache, &clusterv1.Cluster{}), +// handler.EnqueueRequestsFromMapFunc(clusterToMachines) // predicates.ClusterUnpaused(r.Log), // ) func ClusterUnpaused(logger logr.Logger) predicate.Funcs { @@ -175,10 +173,8 @@ func ClusterUnpaused(logger logr.Logger) predicate.Funcs { // Example use: // // err := controller.Watch( -// &source.Kind{Type: &clusterv1.Cluster{}}, -// &handler.EnqueueRequestsFromMapFunc{ -// ToRequests: clusterToMachines, -// }, +// source.Kind(cache, &clusterv1.Cluster{}), +// handler.EnqueueRequestsFromMapFunc(clusterToMachines) // predicates.ClusterControlPlaneInitialized(r.Log), // ) func ClusterControlPlaneInitialized(logger logr.Logger) predicate.Funcs { @@ -218,10 +214,8 @@ func ClusterControlPlaneInitialized(logger logr.Logger) predicate.Funcs { // Example use: // // err := controller.Watch( -// &source.Kind{Type: &clusterv1.Cluster{}}, -// &handler.EnqueueRequestsFromMapFunc{ -// ToRequests: clusterToMachines, -// }, +// source.Kind(cache, &clusterv1.Cluster{}), +// handler.EnqueueRequestsFromMapFunc(clusterToMachines) // predicates.ClusterUnpausedAndInfrastructureReady(r.Log), // ) func ClusterUnpausedAndInfrastructureReady(logger logr.Logger) predicate.Funcs { diff --git a/util/retry.go b/util/retry.go index d037ecca955a..378476a0bd38 100644 --- a/util/retry.go +++ b/util/retry.go @@ -49,12 +49,18 @@ func Retry(fn wait.ConditionFunc, initialBackoffSec int) error { // Poll tries a condition func until it returns true, an error, or the timeout // is reached. +// +// Deprecated: This function has been deprecated and will be removed in a future release. +// Please use utils from "k8s.io/apimachinery/pkg/util/wait" instead. func Poll(interval, timeout time.Duration, condition wait.ConditionFunc) error { return wait.Poll(interval, timeout, condition) } // PollImmediate tries a condition func until it returns true, an error, or the timeout // is reached. +// +// Deprecated: This function has been deprecated and will be removed in a future release. +// Please use utils from "k8s.io/apimachinery/pkg/util/wait" instead. func PollImmediate(interval, timeout time.Duration, condition wait.ConditionFunc) error { return wait.PollImmediate(interval, timeout, condition) } diff --git a/util/util.go b/util/util.go index ea16eaa8f43f..0c3c307da79b 100644 --- a/util/util.go +++ b/util/util.go @@ -198,7 +198,7 @@ func ObjectKey(object metav1.Object) client.ObjectKey { // Cluster events and returns reconciliation requests for an infrastructure provider object. func ClusterToInfrastructureMapFunc(ctx context.Context, gvk schema.GroupVersionKind, c client.Client, providerCluster client.Object) handler.MapFunc { log := ctrl.LoggerFrom(ctx) - return func(o client.Object) []reconcile.Request { + return func(ctx context.Context, o client.Object) []reconcile.Request { cluster, ok := o.(*clusterv1.Cluster) if !ok { return nil @@ -265,7 +265,7 @@ func GetMachineByName(ctx context.Context, c client.Client, namespace, name stri // MachineToInfrastructureMapFunc returns a handler.ToRequestsFunc that watches for // Machine events and returns reconciliation requests for an infrastructure provider object. func MachineToInfrastructureMapFunc(gvk schema.GroupVersionKind) handler.MapFunc { - return func(o client.Object) []reconcile.Request { + return func(_ context.Context, o client.Object) []reconcile.Request { m, ok := o.(*clusterv1.Machine) if !ok { return nil @@ -481,7 +481,7 @@ func ClusterToObjectsMapper(c client.Client, ro client.ObjectList, scheme *runti return nil, err } - return func(o client.Object) []ctrl.Request { + return func(ctx context.Context, o client.Object) []ctrl.Request { cluster, ok := o.(*clusterv1.Cluster) if !ok { return nil @@ -499,7 +499,7 @@ func ClusterToObjectsMapper(c client.Client, ro client.ObjectList, scheme *runti list := &unstructured.UnstructuredList{} list.SetGroupVersionKind(gvk) - if err := c.List(context.TODO(), list, listOpts...); err != nil { + if err := c.List(ctx, list, listOpts...); err != nil { return nil } diff --git a/util/util_test.go b/util/util_test.go index 86fcfd83294c..5d3e88e69c9c 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -103,7 +103,7 @@ func TestMachineToInfrastructureMapFunc(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { fn := MachineToInfrastructureMapFunc(tc.input) - out := fn(tc.request) + out := fn(ctx, tc.request) g.Expect(out).To(Equal(tc.output)) }) } @@ -225,7 +225,7 @@ func TestClusterToInfrastructureMapFunc(t *testing.T) { referenceObject.SetKind(tc.request.Spec.InfrastructureRef.Kind) fn := ClusterToInfrastructureMapFunc(context.Background(), tc.input, clientBuilder.Build(), referenceObject) - out := fn(tc.request) + out := fn(ctx, tc.request) g.Expect(out).To(Equal(tc.output)) }) } @@ -741,7 +741,7 @@ func TestClusterToObjectsMapper(t *testing.T) { client := fake.NewClientBuilder().WithObjects(tc.objects...).WithRESTMapper(restMapper).Build() f, err := ClusterToObjectsMapper(client, tc.input, scheme) g.Expect(err != nil, err).To(Equal(tc.expectError)) - g.Expect(f(cluster)).To(ConsistOf(tc.output)) + g.Expect(f(ctx, cluster)).To(ConsistOf(tc.output)) } }