diff --git a/go.mod b/go.mod index a550e009e9..1f274b10fc 100644 --- a/go.mod +++ b/go.mod @@ -51,9 +51,6 @@ replace ( k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.35.3 k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.35.3 k8s.io/sample-controller => k8s.io/sample-controller v0.35.3 - - // cluster-api-provider-vsphere v1.14.0 dependends on a cluster-api placeholder - sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v1.11.5 ) require ( diff --git a/go.sum b/go.sum index e18ec07929..5dcd093cae 100644 --- a/go.sum +++ b/go.sum @@ -950,8 +950,8 @@ pkg.package-operator.run/boxcutter v0.13.1 h1:FvrSBnHWuf6Co+HPyxRSw2Y5mHSkUtteW8 pkg.package-operator.run/boxcutter v0.13.1/go.mod h1:rR2jd32uNt2eml7UvlYNCpCAYIpTALDzHxaftMfgkZo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 h1:qPrZsv1cwQiFeieFlRqT627fVZ+tyfou/+S5S0H5ua0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/cluster-api v1.11.5 h1:mKQAfB8+6l2uxtEvQ6Z5EIcTObdPNs3TL4DcJScchGo= -sigs.k8s.io/cluster-api v1.11.5/go.mod h1:n0d6BAo8s9+KRap8Wv/IllfmwnSN5XFTWNJuq2gKNlg= +sigs.k8s.io/cluster-api v1.12.3 h1:cuOl3fWXhlXFuQcyIH4C8i3ns8rLhtcnK+x00MVdKBs= +sigs.k8s.io/cluster-api v1.12.3/go.mod h1:EAiTJtf/8M5eBetPwumi6t8DJJ55Ln6Fkvh2OAa7PD4= sigs.k8s.io/cluster-api-provider-aws/v2 v2.10.2 h1:jg4R4FGVWLU/oHMsFPoYQHCxyykvixWKKU3k+OuknlE= sigs.k8s.io/cluster-api-provider-aws/v2 v2.10.2/go.mod h1:pHOUXfzTJ4G5xbvEaal6tK4KqGBI/Ij2Xug4hAR1LGE= sigs.k8s.io/cluster-api-provider-azure v1.22.1 h1:BAzjKZR6Fzwu4oq0AwAeILT/FoyEzS/uw+tnAxoOpMo= diff --git a/go.work b/go.work index f1521b875a..13140341f1 100644 --- a/go.work +++ b/go.work @@ -8,9 +8,6 @@ use ( ) replace ( - // This is required to resolve a placeholder dep in CAPV - sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v1.11.5 - // Pin these specific provider commits until they are included in // releases sigs.k8s.io/cluster-api-provider-aws/v2 => sigs.k8s.io/cluster-api-provider-aws/v2 v2.10.1-0.20260311200936-f3440f3ea2f2 diff --git a/go.work.sum b/go.work.sum index fef7e3ced2..6a0e6319ce 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1658,6 +1658,8 @@ sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.9.2/go.mod h1:BgPOvGEdPTyaIWREF sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.4.1/go.mod h1:rEQnoF3pmD1kmAFQCwA/SqHiiftLFeMwdQt0gsuKWbM= sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader v0.8.4/go.mod h1:RgIi9n/PhULbvPjYZGsjP2zWJf1ZEd1qyA0CYUuSgcE= sigs.k8s.io/cluster-api v1.10.2/go.mod h1:/b9Un5Imprib6S7ZOcJitC2ep/5wN72b0pXpMQFfbTw= +sigs.k8s.io/cluster-api v1.11.5 h1:mKQAfB8+6l2uxtEvQ6Z5EIcTObdPNs3TL4DcJScchGo= +sigs.k8s.io/cluster-api v1.11.5/go.mod h1:n0d6BAo8s9+KRap8Wv/IllfmwnSN5XFTWNJuq2gKNlg= sigs.k8s.io/cluster-api-provider-aws/v2 v2.8.4/go.mod h1:ubZXYyieYt+I4jQFJ47J9Hq4W3zPernTWXlIfIZnB3Y= sigs.k8s.io/cluster-api-provider-aws/v2 v2.10.1-0.20260311200936-f3440f3ea2f2 h1:lzlMuS1F9qub8hw+fm2oo8UzJmUGZ8t9lwf4m8So93E= sigs.k8s.io/cluster-api-provider-aws/v2 v2.10.1-0.20260311200936-f3440f3ea2f2/go.mod h1:vbVa187QP4/y7/03JqhYBmou4xabCRnuRoHwhE2BgE8= diff --git a/pkg/conversion/capi2mapi/common.go b/pkg/conversion/capi2mapi/common.go index 190c2da516..c0ffea257a 100644 --- a/pkg/conversion/capi2mapi/common.go +++ b/pkg/conversion/capi2mapi/common.go @@ -21,6 +21,7 @@ import ( "strings" "github.com/openshift/cluster-capi-operator/pkg/util" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -133,6 +134,24 @@ func convertCAPIMachineAnnotationsToMAPIMachineSpecObjectMetaAnnotations(capiAnn return mapiAnnotations } +func convertCAPITaintsToMAPITaints(capiTaints []clusterv1.MachineTaint) []corev1.Taint { + if len(capiTaints) == 0 { + return nil + } + + mapiTaints := make([]corev1.Taint, len(capiTaints)) + + for i, t := range capiTaints { + mapiTaints[i] = corev1.Taint{ + Key: t.Key, + Value: t.Value, + Effect: t.Effect, + } + } + + return mapiTaints +} + func convertCAPIAnnotationsToMAPIAnnotations(capiAnnotations map[string]string, machineAPIAnnotations map[string]string) map[string]string { if len(capiAnnotations) == 0 && len(machineAPIAnnotations) == 0 { return nil diff --git a/pkg/conversion/capi2mapi/machine.go b/pkg/conversion/capi2mapi/machine.go index 28c714c1e4..e1c544e87f 100644 --- a/pkg/conversion/capi2mapi/machine.go +++ b/pkg/conversion/capi2mapi/machine.go @@ -63,8 +63,8 @@ func fromCAPIMachineToMAPIMachine(capiMachine *clusterv1.Machine, additionalMach }, ProviderID: providerID, LifecycleHooks: lifecycleHooks, + Taints: convertCAPITaintsToMAPITaints(capiMachine.Spec.Taints), // ProviderSpec: // ProviderSpec MUST NOT be populated here. It is added later by higher level fuctions. - // Taints: // TODO(OCPCLOUD-2861): Taint propagation from Machines to Nodes is not yet implemented in CAPI. }, Status: mapiMachineStatus, } diff --git a/pkg/conversion/capi2mapi/machine_test.go b/pkg/conversion/capi2mapi/machine_test.go index 36bf2d2cae..b3356fc552 100644 --- a/pkg/conversion/capi2mapi/machine_test.go +++ b/pkg/conversion/capi2mapi/machine_test.go @@ -97,7 +97,59 @@ var _ = Describe("capi2mapi Machine conversion", func() { Expect(machine.Annotations).ToNot(HaveKey(clusterv1.DeleteMachineAnnotation)) }, }), + + Entry("With no taints on MAPI Machine converted from CAPI", capi2MAPIMachineConversionInput{ + machineBuilder: capiMachineBase, + expectedErrors: []string{}, + expectedWarnings: []string{}, + assertion: func(machine *mapiv1beta1.Machine) { + Expect(machine.Spec.Taints).To(BeEmpty()) + }, + }), ) + + Context("when the CAPI Machine has taints", func() { + It("should convert CAPI Machine taints to MAPI Machine taints", func() { + capiMachine := capiMachineBase.Build() + capiMachine.Spec.Taints = []clusterv1.MachineTaint{{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + Propagation: clusterv1.MachineTaintPropagationAlways, + }} + machine, warns, err := FromMachineAndAWSMachineAndAWSCluster( + capiMachine, + capabuilder.AWSMachine().Build(), + capabuilder.AWSCluster().Build(), + ).ToMachine() + Expect(err).To(BeNil()) + Expect(warns).To(BeEmpty()) + Expect(machine.Spec.Taints).To(ConsistOf(corev1.Taint{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + })) + }) + + It("should convert multiple CAPI Machine taints to MAPI Machine taints, dropping propagation", func() { + capiMachine := capiMachineBase.Build() + capiMachine.Spec.Taints = []clusterv1.MachineTaint{ + {Key: "key1", Value: "value1", Effect: corev1.TaintEffectNoSchedule, Propagation: clusterv1.MachineTaintPropagationAlways}, + {Key: "key2", Value: "value2", Effect: corev1.TaintEffectNoExecute, Propagation: clusterv1.MachineTaintPropagationOnInitialization}, + } + machine, warns, err := FromMachineAndAWSMachineAndAWSCluster( + capiMachine, + capabuilder.AWSMachine().Build(), + capabuilder.AWSCluster().Build(), + ).ToMachine() + Expect(err).To(BeNil()) + Expect(warns).To(BeEmpty()) + Expect(machine.Spec.Taints).To(ConsistOf( + corev1.Taint{Key: "key1", Value: "value1", Effect: corev1.TaintEffectNoSchedule}, + corev1.Taint{Key: "key2", Value: "value2", Effect: corev1.TaintEffectNoExecute}, + )) + }) + }) }) var _ = Describe("capi2mapi Machine Status Conversion", func() { diff --git a/pkg/conversion/mapi2capi/machine.go b/pkg/conversion/mapi2capi/machine.go index 5876084a05..979197ed11 100644 --- a/pkg/conversion/mapi2capi/machine.go +++ b/pkg/conversion/mapi2capi/machine.go @@ -67,6 +67,7 @@ func fromMAPIMachineToCAPIMachine(mapiMachine *mapiv1beta1.Machine, apiGroup, ki Deletion: clusterv1.MachineDeletionSpec{ NodeDeletionTimeoutSeconds: ptr.To[int32](10), // Hardcode it to the CAPI default value until this is implemented in MAPI. }, + Taints: convertMAPITaintsToCAPITaints(mapiMachine.Spec.Taints), }, Status: capiMachineStatus, } diff --git a/pkg/conversion/mapi2capi/machine_test.go b/pkg/conversion/mapi2capi/machine_test.go index 06da0cd8e1..da093200b7 100644 --- a/pkg/conversion/mapi2capi/machine_test.go +++ b/pkg/conversion/mapi2capi/machine_test.go @@ -46,12 +46,12 @@ var _ = Describe("mapi2capi Machine conversion", func() { infraBuilder configbuilder.InfrastructureBuilder expectedErrors []string expectedWarnings []string - assertion func(machine *mapiv1beta1.Machine) + assertion func(capiMachine *clusterv1.Machine) } var _ = DescribeTable("mapi2capi convert MAPI Machine to a CAPI Machine", func(in mapi2CAPIMachineConversionInput) { - _, _, warns, err := FromAWSMachineAndInfra( + capiMachine, _, warns, err := FromAWSMachineAndInfra( in.machineBuilder.Build(), in.infraBuilder.Build(), ).ToMachineAndInfrastructureMachine() @@ -59,6 +59,10 @@ var _ = Describe("mapi2capi Machine conversion", func() { "should match expected errors while converting MAPI Machine to CAPI Machine") Expect(warns).To(matchers.ConsistOfSubstrings(in.expectedWarnings), "should match expected warnings while converting MAPI Machine to CAPI Machine") + + if in.assertion != nil { + in.assertion(capiMachine) + } }, // Base Case. @@ -121,15 +125,85 @@ var _ = Describe("mapi2capi Machine conversion", func() { expectedWarnings: []string{}, }), - Entry("With unsupported spec.taints set", mapi2CAPIMachineConversionInput{ + Entry("With spec.taints set", mapi2CAPIMachineConversionInput{ infraBuilder: infraBase, machineBuilder: mapiMachineBase.WithTaints([]corev1.Taint{{ Key: "key1", Value: "value1", Effect: corev1.TaintEffectNoSchedule, }}), - expectedErrors: []string{"spec.taints: Invalid value: [{\"key\":\"key1\",\"value\":\"value1\",\"effect\":\"NoSchedule\"}]: taints are not currently supported"}, + expectedErrors: []string{}, expectedWarnings: []string{}, + assertion: func(capiMachine *clusterv1.Machine) { + Expect(capiMachine.Spec.Taints).To(ConsistOf(clusterv1.MachineTaint{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + Propagation: clusterv1.MachineTaintPropagationAlways, + })) + }, + }), + + Entry("With spec.taints set with NoExecute effect", mapi2CAPIMachineConversionInput{ + infraBuilder: infraBase, + machineBuilder: mapiMachineBase.WithTaints([]corev1.Taint{{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoExecute, + }}), + expectedErrors: []string{}, + expectedWarnings: []string{}, + assertion: func(capiMachine *clusterv1.Machine) { + Expect(capiMachine.Spec.Taints).To(ConsistOf(clusterv1.MachineTaint{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoExecute, + Propagation: clusterv1.MachineTaintPropagationAlways, + })) + }, + }), + + Entry("With spec.taints set with PreferNoSchedule effect", mapi2CAPIMachineConversionInput{ + infraBuilder: infraBase, + machineBuilder: mapiMachineBase.WithTaints([]corev1.Taint{{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectPreferNoSchedule, + }}), + expectedErrors: []string{}, + expectedWarnings: []string{}, + assertion: func(capiMachine *clusterv1.Machine) { + Expect(capiMachine.Spec.Taints).To(ConsistOf(clusterv1.MachineTaint{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectPreferNoSchedule, + Propagation: clusterv1.MachineTaintPropagationAlways, + })) + }, + }), + + Entry("With multiple spec.taints set", mapi2CAPIMachineConversionInput{ + infraBuilder: infraBase, + machineBuilder: mapiMachineBase.WithTaints([]corev1.Taint{ + { + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Value: "value2", + Effect: corev1.TaintEffectNoExecute, + }, + }), + expectedErrors: []string{}, + expectedWarnings: []string{}, + assertion: func(capiMachine *clusterv1.Machine) { + Expect(capiMachine.Spec.Taints).To(ConsistOf( + clusterv1.MachineTaint{Key: "key1", Value: "value1", Effect: corev1.TaintEffectNoSchedule, Propagation: clusterv1.MachineTaintPropagationAlways}, + clusterv1.MachineTaint{Key: "key2", Value: "value2", Effect: corev1.TaintEffectNoExecute, Propagation: clusterv1.MachineTaintPropagationAlways}, + )) + }, }), Entry("With delete-machine annotation", mapi2CAPIMachineConversionInput{ @@ -137,9 +211,9 @@ var _ = Describe("mapi2capi Machine conversion", func() { machineBuilder: mapiMachineBase.WithAnnotations(map[string]string{util.MapiDeleteMachineAnnotation: "true"}), expectedErrors: []string{}, expectedWarnings: []string{}, - assertion: func(machine *mapiv1beta1.Machine) { - Expect(machine.Annotations).To(HaveKeyWithValue(clusterv1.DeleteMachineAnnotation, "true")) - Expect(machine.Annotations).ToNot(HaveKey(util.MapiDeleteMachineAnnotation)) + assertion: func(capiMachine *clusterv1.Machine) { + Expect(capiMachine.Annotations).To(HaveKeyWithValue(clusterv1.DeleteMachineAnnotation, "true")) + Expect(capiMachine.Annotations).ToNot(HaveKey(util.MapiDeleteMachineAnnotation)) }, }), ) diff --git a/pkg/conversion/mapi2capi/machineset_test.go b/pkg/conversion/mapi2capi/machineset_test.go index 1ad6953d23..492c9d7a04 100644 --- a/pkg/conversion/mapi2capi/machineset_test.go +++ b/pkg/conversion/mapi2capi/machineset_test.go @@ -43,11 +43,12 @@ var _ = Describe("mapi2capi MachineSet conversion", func() { infraBuilder configbuilder.InfrastructureBuilder expectedErrors []string expectedWarnings []string + assertion func(capiMachineSet *clusterv1.MachineSet) } var _ = DescribeTable("mapi2capi convert MAPI MachineSet to CAPI MachineSet", func(in mapi2CAPIMachinesetConversionInput) { - _, _, warns, err := FromAWSMachineSetAndInfra( + capiMachineSet, _, warns, err := FromAWSMachineSetAndInfra( in.machineSetBuilder.Build(), in.infraBuilder.Build(), ).ToMachineSetAndMachineTemplate() @@ -55,6 +56,10 @@ var _ = Describe("mapi2capi MachineSet conversion", func() { "should match expected errors while converting MAPI MachineSet to CAPI MachineSet") Expect(warns).To(matchers.ConsistOfSubstrings(in.expectedWarnings), "should match expected warnings while converting MAPI MachineSet to CAPI MachineSet") + + if in.assertion != nil { + in.assertion(capiMachineSet) + } }, // Base Case @@ -91,6 +96,25 @@ var _ = Describe("mapi2capi MachineSet conversion", func() { expectedErrors: []string{"spec.metadata.namespace: Invalid value: \"test-namespace\": namespace is not supported"}, expectedWarnings: []string{}, }), + + Entry("With spec.taints set", mapi2CAPIMachinesetConversionInput{ + infraBuilder: infraBase, + machineSetBuilder: mapiMachineSetBase.WithTaints([]corev1.Taint{{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + }}), + expectedErrors: []string{}, + expectedWarnings: []string{}, + assertion: func(capiMachineSet *clusterv1.MachineSet) { + Expect(capiMachineSet.Spec.Template.Spec.Taints).To(ConsistOf(clusterv1.MachineTaint{ + Key: "key1", + Value: "value1", + Effect: corev1.TaintEffectNoSchedule, + Propagation: clusterv1.MachineTaintPropagationAlways, + })) + }, + }), ) }) diff --git a/pkg/conversion/mapi2capi/util.go b/pkg/conversion/mapi2capi/util.go index e844c023db..ee957b8463 100644 --- a/pkg/conversion/mapi2capi/util.go +++ b/pkg/conversion/mapi2capi/util.go @@ -24,6 +24,7 @@ import ( mapiv1beta1 "github.com/openshift/api/machine/v1beta1" "github.com/openshift/cluster-capi-operator/pkg/conversion/consts" "github.com/openshift/cluster-capi-operator/pkg/util" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -149,6 +150,26 @@ func setMAPINodeLabelsToCAPINodeLabels(mapiNodeLabels map[string]string, capiMac } } +func convertMAPITaintsToCAPITaints(mapiTaints []corev1.Taint) []clusterv1.MachineTaint { + if len(mapiTaints) == 0 { + return nil + } + + capiTaints := make([]clusterv1.MachineTaint, len(mapiTaints)) + + for i, t := range mapiTaints { + capiTaints[i] = clusterv1.MachineTaint{ + Key: t.Key, + Value: t.Value, + Effect: t.Effect, + // MAPI taints are actively reconciled, which maps to Always propagation in CAPI. + Propagation: clusterv1.MachineTaintPropagationAlways, + } + } + + return capiTaints +} + // setCAPILifecycleHookAnnotations sets the annotations that should be added to a CAPI Machine to represent the lifecycle hooks. func setCAPILifecycleHookAnnotations(hooks mapiv1beta1.LifecycleHooks, capiMachine *clusterv1.Machine) { lifecycleAnnotations := make(map[string]string) @@ -172,18 +193,7 @@ func setCAPILifecycleHookAnnotations(hooks mapiv1beta1.LifecycleHooks, capiMachi // handleUnsupportedMachineFields checks for fields that are not supported by CAPI and returns a list of errors. func handleUnsupportedMachineFields(spec mapiv1beta1.MachineSpec) field.ErrorList { - var errs field.ErrorList - - fldPath := field.NewPath("spec") - - errs = append(errs, handleUnsupportedMAPIObjectMetaFields(fldPath.Child("metadata"), spec.ObjectMeta)...) - - // TODO(OCPCLOUD-2861/2899): Taints are not supported by CAPI. add support for them via CAPI BootstrapConfig + minimal bootstrap controller. - if len(spec.Taints) > 0 { - errs = append(errs, field.Invalid(fldPath.Child("taints"), spec.Taints, "taints are not currently supported")) - } - - return errs + return handleUnsupportedMAPIObjectMetaFields(field.NewPath("spec").Child("metadata"), spec.ObjectMeta) } // handleUnsupportedMAPIObjectMetaFields checks for unsupported MAPI metadta fields and returns a list of errors diff --git a/pkg/conversion/test/fuzz/fuzz.go b/pkg/conversion/test/fuzz/fuzz.go index ad9dd335f6..f42807384f 100644 --- a/pkg/conversion/test/fuzz/fuzz.go +++ b/pkg/conversion/test/fuzz/fuzz.go @@ -473,6 +473,8 @@ func ObjectMetaFuzzerFuncs(namespace string) fuzzer.FuzzerFuncs { } // CAPIMachineFuzzerFuncs returns a set of fuzzer functions that can be used to fuzz MachineSpec objects. +// +//nolint:funlen func CAPIMachineFuzzerFuncs(providerIDFuzz StringFuzzer, infraKind, infraAPIGroup, clusterName string) fuzzer.FuzzerFuncs { return func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ @@ -507,6 +509,15 @@ func CAPIMachineFuzzerFuncs(providerIDFuzz StringFuzzer, infraKind, infraAPIGrou if infraKind == powerVSMachineKind { m.FailureDomain = "" } + + // Normalize taints: empty→nil (MAPI uses nil), all Propagation→Always (MAPI has no propagation concept). + if len(m.Taints) == 0 { + m.Taints = nil + } else { + for i := range m.Taints { + m.Taints[i].Propagation = clusterv1.MachineTaintPropagationAlways + } + } }, func(m *clusterv1.Machine, c randfill.Continue) { c.FillNoCustom(m) diff --git a/vendor/modules.txt b/vendor/modules.txt index 735fc4d928..b6c3635e8d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -3035,7 +3035,7 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/common/metrics sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client -# sigs.k8s.io/cluster-api v1.12.3 => sigs.k8s.io/cluster-api v1.11.5 +# sigs.k8s.io/cluster-api v1.12.3 ## explicit; go 1.24.0 sigs.k8s.io/cluster-api/api/core/v1beta1 sigs.k8s.io/cluster-api/api/core/v1beta2 @@ -3307,7 +3307,6 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 -# sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v1.11.5 # sigs.k8s.io/cluster-api-provider-aws/v2 => sigs.k8s.io/cluster-api-provider-aws/v2 v2.10.1-0.20260311200936-f3440f3ea2f2 # sigs.k8s.io/cluster-api-provider-azure => sigs.k8s.io/cluster-api-provider-azure v1.22.1-0.20260313010140-0c77ca282778 # sigs.k8s.io/cluster-api-provider-gcp => sigs.k8s.io/cluster-api-provider-gcp v1.11.0-beta.0.0.20260312083137-58abcdcc039b diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/cluster_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/cluster_types.go index c6ff0853b1..5d6d69a9b3 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/cluster_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/cluster_types.go @@ -1092,12 +1092,12 @@ func (c *ClusterStatus) GetTypedPhase() ClusterPhase { type APIEndpoint struct { // host is the hostname on which the API server is serving. // TODO: Can't set MinLength=1 for now, because this struct is not always used in pointer fields so today we have cases where host is set to an empty string. - // +required + // +optional // +kubebuilder:validation:MaxLength=512 Host string `json:"host"` // port is the port on which the API server is serving. - // +required + // +optional Port int32 `json:"port"` } diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/conversion.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/conversion.go index 03d7a7a9ad..a240707da7 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/conversion.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/conversion.go @@ -73,6 +73,11 @@ func (src *Cluster) ConvertTo(dstRaw conversion.Hub) error { return err } + dst.Spec.Topology.ControlPlane.HealthCheck.Checks.UnhealthyMachineConditions = restored.Spec.Topology.ControlPlane.HealthCheck.Checks.UnhealthyMachineConditions + for i, md := range restored.Spec.Topology.Workers.MachineDeployments { + dst.Spec.Topology.Workers.MachineDeployments[i].HealthCheck.Checks.UnhealthyMachineConditions = md.HealthCheck.Checks.UnhealthyMachineConditions + } + // Recover intent for bool values converted to *bool. clusterv1.Convert_bool_To_Pointer_bool(src.Spec.Paused, ok, restored.Spec.Paused, &dst.Spec.Paused) @@ -145,6 +150,11 @@ func (src *ClusterClass) ConvertTo(dstRaw conversion.Hub) error { return err } + dst.Spec.ControlPlane.HealthCheck.Checks.UnhealthyMachineConditions = restored.Spec.ControlPlane.HealthCheck.Checks.UnhealthyMachineConditions + for i, md := range restored.Spec.Workers.MachineDeployments { + dst.Spec.Workers.MachineDeployments[i].HealthCheck.Checks.UnhealthyMachineConditions = md.HealthCheck.Checks.UnhealthyMachineConditions + } + // Recover intent for bool values converted to *bool. for i, patch := range dst.Spec.Patches { for j, definition := range patch.Definitions { @@ -248,6 +258,10 @@ func (src *ClusterClass) ConvertTo(dstRaw conversion.Hub) error { dst.Status.Variables[i] = variable } + dst.Spec.KubernetesVersions = restored.Spec.KubernetesVersions + + dst.Spec.Upgrade.External.GenerateUpgradePlanExtension = restored.Spec.Upgrade.External.GenerateUpgradePlanExtension + return nil } @@ -394,6 +408,11 @@ func (src *Machine) ConvertTo(dstRaw conversion.Hub) error { // Recover other values. if ok { dst.Spec.MinReadySeconds = restored.Spec.MinReadySeconds + dst.Spec.Taints = restored.Spec.Taints + // Restore the phase, this also means that any client using v1beta1 during a round-trip + // won't be able to write the Phase field. But that's okay as the only client writing the Phase + // field should be the Machine controller. + dst.Status.Phase = restored.Status.Phase } return nil @@ -432,6 +451,17 @@ func (src *MachineSet) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.Template.Spec.MinReadySeconds = &src.Spec.MinReadySeconds } + restored := &clusterv1.MachineSet{} + ok, err := utilconversion.UnmarshalData(src, restored) + if err != nil { + return err + } + + // Recover other values + if ok { + dst.Spec.Template.Spec.Taints = restored.Spec.Template.Spec.Taints + } + return nil } @@ -449,7 +479,8 @@ func (dst *MachineSet) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.MinReadySeconds = ptr.Deref(src.Spec.Template.Spec.MinReadySeconds, 0) dropEmptyStringsMachineSpec(&dst.Spec.Template.Spec) - return nil + + return utilconversion.MarshalData(src, dst) } func (src *MachineDeployment) ConvertTo(dstRaw conversion.Hub) error { @@ -474,6 +505,11 @@ func (src *MachineDeployment) ConvertTo(dstRaw conversion.Hub) error { // Recover intent for bool values converted to *bool. clusterv1.Convert_bool_To_Pointer_bool(src.Spec.Paused, ok, restored.Spec.Paused, &dst.Spec.Paused) + // Recover other values + if ok { + dst.Spec.Template.Spec.Taints = restored.Spec.Template.Spec.Taints + } + return nil } @@ -509,6 +545,8 @@ func (src *MachineHealthCheck) ConvertTo(dstRaw conversion.Hub) error { return err } + dst.Spec.Checks.UnhealthyMachineConditions = restored.Spec.Checks.UnhealthyMachineConditions + clusterv1.Convert_int32_To_Pointer_int32(src.Status.ExpectedMachines, ok, restored.Status.ExpectedMachines, &dst.Status.ExpectedMachines) clusterv1.Convert_int32_To_Pointer_int32(src.Status.CurrentHealthy, ok, restored.Status.CurrentHealthy, &dst.Status.CurrentHealthy) clusterv1.Convert_int32_To_Pointer_int32(src.Status.RemediationsAllowed, ok, restored.Status.RemediationsAllowed, &dst.Status.RemediationsAllowed) @@ -558,6 +596,11 @@ func (src *MachinePool) ConvertTo(dstRaw conversion.Hub) error { dst.Status.Initialization = initialization } + // Recover other values + if ok { + dst.Spec.Template.Spec.Taints = restored.Spec.Template.Spec.Taints + } + return nil } @@ -1637,6 +1680,13 @@ func Convert_v1beta2_MachineStatus_To_v1beta1_MachineStatus(in *clusterv1.Machin if err := autoConvert_v1beta2_MachineStatus_To_v1beta1_MachineStatus(in, out, s); err != nil { return err } + + // Convert v1beta2 Updating phase to v1beta1 Running as Updating did not exist in v1beta1. + // We don't have to support a round-trip as only the core CAPI controller should write the Phase field. + if out.Phase == "Updating" { + out.Phase = "Running" + } + if !reflect.DeepEqual(in.LastUpdated, metav1.Time{}) { out.LastUpdated = ptr.To(in.LastUpdated) } @@ -2285,8 +2335,6 @@ func convertToObjectReference(ref clusterv1.ContractVersionedObjectReference, na } func Convert_v1beta1_JSONSchemaProps_To_v1beta2_JSONSchemaProps(in *JSONSchemaProps, out *clusterv1.JSONSchemaProps, s apimachineryconversion.Scope) error { - // This conversion func is also required due to a bug in conversion gen that does not recognize the changes for converting bool to *bool. - // By implementing this func, autoConvert_v1beta1_JSONSchemaProps_To_v1beta2_JSONSchemaProps is generated properly. if err := autoConvert_v1beta1_JSONSchemaProps_To_v1beta2_JSONSchemaProps(in, out, s); err != nil { return err } diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/machine_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/machine_types.go index 9665953dd4..5a37f75427 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/machine_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/machine_types.go @@ -66,10 +66,10 @@ const ( // * KCP adds its own pre-terminate hook on all Machines it controls. This is done to ensure it can later remove // the etcd member right before Machine termination (i.e. before InfraMachine deletion). // * Starting with Kubernetes v1.31 the KCP pre-terminate hook will wait for all other pre-terminate hooks to finish to - // ensure it runs last (thus ensuring that kubelet is still working while other pre-terminate hooks run). This is only done - // for v1.31 or above because the kubeadm ControlPlaneKubeletLocalMode was introduced with kubeadm 1.31. This feature configures - // the kubelet to communicate with the local apiserver. Only because of that the kubelet immediately starts failing after the etcd - // member is removed. We need the ControlPlaneKubeletLocalMode feature with 1.31 to adhere to the kubelet skew policy. + // ensure it runs last (thus ensuring that kubelet is still working while other pre-terminate hooks run). This is done + // for v1.31 or above because the kubeadm ControlPlaneKubeletLocalMode was introduced with kubeadm 1.31 (graduated to GA in 1.36). + // This feature configures the kubelet to communicate with the local apiserver. Only because of that the kubelet immediately + // starts failing after the etcd member is removed. We need the ControlPlaneKubeletLocalMode feature with 1.31+ to adhere to the kubelet skew policy. PreTerminateDeleteHookAnnotationPrefix = "pre-terminate.delete.hook.machine.cluster.x-k8s.io" // MachineCertificatesExpiryDateAnnotation annotation specifies the expiry date of the machine certificates in RFC3339 format. diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.conversion.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.conversion.go index eb54f254dd..c0514e67d2 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.conversion.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.conversion.go @@ -1207,6 +1207,8 @@ func autoConvert_v1beta2_ClusterClassSpec_To_v1beta1_ClusterClassSpec(in *v1beta } else { out.Patches = nil } + // WARNING: in.Upgrade requires manual conversion: does not exist in peer-type + // WARNING: in.KubernetesVersions requires manual conversion: does not exist in peer-type return nil } @@ -3165,6 +3167,7 @@ func autoConvert_v1beta2_MachineSpec_To_v1beta1_MachineSpec(in *v1beta2.MachineS // WARNING: in.MinReadySeconds requires manual conversion: does not exist in peer-type out.ReadinessGates = *(*[]MachineReadinessGate)(unsafe.Pointer(&in.ReadinessGates)) // WARNING: in.Deletion requires manual conversion: does not exist in peer-type + // WARNING: in.Taints requires manual conversion: does not exist in peer-type return nil } diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.openapi.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.openapi.go index 13a78b2371..723cf5a90c 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.openapi.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta1/zz_generated.openapi.go @@ -154,7 +154,6 @@ func schema_cluster_api_api_core_v1beta1_APIEndpoint(ref common.ReferenceCallbac }, }, }, - Required: []string{"host", "port"}, }, }, } diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/cluster_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/cluster_types.go index af09698531..9666455e90 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/cluster_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/cluster_types.go @@ -80,17 +80,27 @@ const ( // failing due to an error. ClusterTopologyReconciledFailedReason = "ReconcileFailed" + // ClusterTopologyReconciledClusterCreatingReason documents reconciliation of a Cluster topology + // not yet created because the BeforeClusterCreate hook is blocking. + ClusterTopologyReconciledClusterCreatingReason = "ClusterCreating" + // ClusterTopologyReconciledControlPlaneUpgradePendingReason documents reconciliation of a Cluster topology // not yet completed because Control Plane is not yet updated to match the desired topology spec. + // + // Deprecated: please use ClusterUpgrading instead. ClusterTopologyReconciledControlPlaneUpgradePendingReason = "ControlPlaneUpgradePending" // ClusterTopologyReconciledMachineDeploymentsCreatePendingReason documents reconciliation of a Cluster topology // not yet completed because at least one of the MachineDeployments is yet to be created. // This generally happens because new MachineDeployment creations are held off while the ControlPlane is not stable. + // + // Deprecated: please use ClusterUpgrading instead. ClusterTopologyReconciledMachineDeploymentsCreatePendingReason = "MachineDeploymentsCreatePending" // ClusterTopologyReconciledMachineDeploymentsUpgradePendingReason documents reconciliation of a Cluster topology // not yet completed because at least one of the MachineDeployments is not yet updated to match the desired topology spec. + // + // Deprecated: please use ClusterUpgrading instead. ClusterTopologyReconciledMachineDeploymentsUpgradePendingReason = "MachineDeploymentsUpgradePending" // ClusterTopologyReconciledMachineDeploymentsUpgradeDeferredReason documents reconciliation of a Cluster topology @@ -99,11 +109,15 @@ const ( // ClusterTopologyReconciledMachinePoolsUpgradePendingReason documents reconciliation of a Cluster topology // not yet completed because at least one of the MachinePools is not yet updated to match the desired topology spec. + // + // Deprecated: please use ClusterUpgrading instead. ClusterTopologyReconciledMachinePoolsUpgradePendingReason = "MachinePoolsUpgradePending" // ClusterTopologyReconciledMachinePoolsCreatePendingReason documents reconciliation of a Cluster topology // not yet completed because at least one of the MachinePools is yet to be created. // This generally happens because new MachinePool creations are held off while the ControlPlane is not stable. + // + // Deprecated: please use ClusterUpgrading instead. ClusterTopologyReconciledMachinePoolsCreatePendingReason = "MachinePoolsCreatePending" // ClusterTopologyReconciledMachinePoolsUpgradeDeferredReason documents reconciliation of a Cluster topology @@ -112,8 +126,13 @@ const ( // ClusterTopologyReconciledHookBlockingReason documents reconciliation of a Cluster topology // not yet completed because at least one of the lifecycle hooks is blocking. + // + // Deprecated: please use ClusterUpgrading instead. ClusterTopologyReconciledHookBlockingReason = "LifecycleHookBlocking" + // ClusterTopologyReconciledClusterUpgradingReason documents reconciliation of a Cluster topology + // not yet completed because a cluster upgrade is still in progress. + ClusterTopologyReconciledClusterUpgradingReason = "ClusterUpgrading" // ClusterTopologyReconciledClusterClassNotReconciledReason documents reconciliation of a Cluster topology not // yet completed because the ClusterClass has not reconciled yet. If this condition persists there may be an issue // with the ClusterClass surfaced in the ClusterClass status or controller logs. @@ -725,6 +744,16 @@ type ControlPlaneTopologyHealthCheckChecks struct { // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a machine is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the machine is unhealthy. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` } // ControlPlaneTopologyHealthCheckRemediation configures if and how remediations are triggered if a control plane Machine is unhealthy. @@ -975,6 +1004,16 @@ type MachineDeploymentTopologyHealthCheckChecks struct { // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a machine is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the machine is unhealthy. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` } // MachineDeploymentTopologyHealthCheckRemediation configures if and how remediations are triggered if a MachineDeployment Machine is unhealthy. diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/clusterclass_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/clusterclass_types.go index 80d78f3585..12e8cc19c5 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/clusterclass_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/clusterclass_types.go @@ -135,6 +135,22 @@ type ClusterClassSpec struct { // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=1000 Patches []ClusterClassPatch `json:"patches,omitempty"` + + // upgrade defines the upgrade configuration for clusters using this ClusterClass. + // +optional + Upgrade ClusterClassUpgrade `json:"upgrade,omitempty,omitzero"` + + // kubernetesVersions is the list of Kubernetes versions that can be + // used for clusters using this ClusterClass. + // The list of version must be ordered from the older to the newer version, and there should be + // at least one version for every minor in between the first and the last version. + // +optional + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + // +kubebuilder:validation:items:MinLength=1 + // +kubebuilder:validation:items:MaxLength=256 + KubernetesVersions []string `json:"kubernetesVersions,omitempty"` } // InfrastructureClass defines the class for the infrastructure cluster. @@ -265,6 +281,16 @@ type ControlPlaneClassHealthCheckChecks struct { // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a machine is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the machine is unhealthy. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` } // ControlPlaneClassHealthCheckRemediation configures if and how remediations are triggered if a control plane Machine is unhealthy. @@ -526,6 +552,16 @@ type MachineDeploymentClassHealthCheckChecks struct { // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a machine is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the machine is unhealthy. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` } // MachineDeploymentClassHealthCheckRemediation configures if and how remediations are triggered if a MachineDeployment Machine is unhealthy. @@ -1240,6 +1276,24 @@ type ClusterClassPatch struct { External *ExternalPatchDefinition `json:"external,omitempty"` } +// ClusterClassUpgrade defines the upgrade configuration for clusters using the ClusterClass. +// +kubebuilder:validation:MinProperties=1 +type ClusterClassUpgrade struct { + // external defines external runtime extensions for upgrade operations. + // +optional + External ClusterClassUpgradeExternal `json:"external,omitempty,omitzero"` +} + +// ClusterClassUpgradeExternal defines external runtime extensions for upgrade operations. +// +kubebuilder:validation:MinProperties=1 +type ClusterClassUpgradeExternal struct { + // generateUpgradePlanExtension references an extension which is called to generate upgrade plan. + // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=512 + GenerateUpgradePlanExtension string `json:"generateUpgradePlanExtension,omitempty"` +} + // PatchDefinition defines a patch which is applied to customize the referenced templates. type PatchDefinition struct { // selector defines on which templates the patch should be applied. diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/common_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/common_types.go index 9e409f6928..78b064afb1 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/common_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/common_types.go @@ -36,6 +36,10 @@ const ( // to track the name of the MachineDeployment topology it represents. ClusterTopologyMachineDeploymentNameLabel = "topology.cluster.x-k8s.io/deployment-name" + // ClusterTopologyUpgradeStepAnnotation tracks the version of the current upgrade step. + // It is only set when an upgrade is in progress, and it contains the control plane version computed by topology controller. + ClusterTopologyUpgradeStepAnnotation = "topology.internal.cluster.x-k8s.io/upgrade-step" + // ClusterTopologyHoldUpgradeSequenceAnnotation can be used to hold the entire MachineDeployment upgrade sequence. // If the annotation is set on a MachineDeployment topology in Cluster.spec.topology.workers, the Kubernetes upgrade // for this MachineDeployment topology and all subsequent ones is deferred. @@ -95,6 +99,9 @@ const ( // AnnotationsFromMachineAnnotation is the annotation set on nodes to track the annotations that originated from machines. AnnotationsFromMachineAnnotation = "cluster.x-k8s.io/annotations-from-machine" + // TaintsFromMachineAnnotation is the annotation set on nodes to track the taints that originated from machines. + TaintsFromMachineAnnotation = "cluster.x-k8s.io/taints-from-machine" + // OwnerNameAnnotation is the annotation set on nodes identifying the owner name. OwnerNameAnnotation = "cluster.x-k8s.io/owner-name" @@ -401,3 +408,58 @@ func (r *ContractVersionedObjectReference) GroupKind() schema.GroupKind { Kind: r.Kind, } } + +// MachineTaint defines a taint equivalent to corev1.Taint, but additionally having a propagation field. +type MachineTaint struct { + // key is the taint key to be applied to a node. + // Must be a valid qualified name of maximum size 63 characters + // with an optional subdomain prefix of maximum size 253 characters, + // separated by a `/`. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=317 + // +kubebuilder:validation:Pattern=^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/)?([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$ + // +kubebuilder:validation:XValidation:rule="self.contains('/') ? ( self.split('/') [0].size() <= 253 && self.split('/') [1].size() <= 63 && self.split('/').size() == 2 ) : self.size() <= 63",message="key must be a valid qualified name of max size 63 characters with an optional subdomain prefix of max size 253 characters" + Key string `json:"key,omitempty"` + + // value is the taint value corresponding to the taint key. + // It must be a valid label value of maximum size 63 characters. + // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + Value string `json:"value,omitempty"` + + // effect is the effect for the taint. Valid values are NoSchedule, PreferNoSchedule and NoExecute. + // +required + // +kubebuilder:validation:Enum=NoSchedule;PreferNoSchedule;NoExecute + Effect corev1.TaintEffect `json:"effect,omitempty"` + + // propagation defines how this taint should be propagated to nodes. + // Valid values are 'Always' and 'OnInitialization'. + // Always: The taint will be continuously reconciled. If it is not set for a node, it will be added during reconciliation. + // OnInitialization: The taint will be added during node initialization. If it gets removed from the node later on it will not get added again. + // +required + Propagation MachineTaintPropagation `json:"propagation,omitempty"` +} + +// MachineTaintPropagation defines when a taint should be propagated to nodes. +// +kubebuilder:validation:Enum=Always;OnInitialization +type MachineTaintPropagation string + +const ( + // MachineTaintPropagationAlways means the taint should be continuously reconciled and kept on the node. + // - If an Always taint is added to the Machine, the taint will be added to the node. + // - If an Always taint is removed from the Machine, the taint will be removed from the node. + // - If an OnInitialization taint is changed to Always, the Machine controller will ensure the taint is set on the node. + // - If an Always taint is removed from the node, it will be re-added during reconciliation. + MachineTaintPropagationAlways MachineTaintPropagation = "Always" + + // MachineTaintPropagationOnInitialization means the taint should be set once during initialization and then + // left alone. + // - If an OnInitialization taint is added to the Machine, the taint will only be added to the node on initialization. + // - If an OnInitialization taint is removed from the Machine nothing will be changed on the node. + // - If an Always taint is changed to OnInitialization, the taint will only be added to the node on initialization. + // - If an OnInitialization taint is removed from the node, it will not be re-added during reconciliation. + MachineTaintPropagationOnInitialization MachineTaintPropagation = "OnInitialization" +) diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_phase_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_phase_types.go index 1ca9551564..b849ea61d6 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_phase_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_phase_types.go @@ -45,6 +45,10 @@ const ( // become a Kubernetes Node in a Ready state. MachinePhaseRunning = MachinePhase("Running") + // MachinePhaseUpdating is the Machine state when the Machine + // is updating. + MachinePhaseUpdating = MachinePhase("Updating") + // MachinePhaseDeleting is the Machine state when a delete // request has been sent to the API Server, // but its infrastructure has not yet been fully deleted. diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_types.go index a60f736ba2..16f4bf07a7 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machine_types.go @@ -66,10 +66,10 @@ const ( // * KCP adds its own pre-terminate hook on all Machines it controls. This is done to ensure it can later remove // the etcd member right before Machine termination (i.e. before InfraMachine deletion). // * Starting with Kubernetes v1.31 the KCP pre-terminate hook will wait for all other pre-terminate hooks to finish to - // ensure it runs last (thus ensuring that kubelet is still working while other pre-terminate hooks run). This is only done - // for v1.31 or above because the kubeadm ControlPlaneKubeletLocalMode was introduced with kubeadm 1.31. This feature configures - // the kubelet to communicate with the local apiserver. Only because of that the kubelet immediately starts failing after the etcd - // member is removed. We need the ControlPlaneKubeletLocalMode feature with 1.31 to adhere to the kubelet skew policy. + // ensure it runs last (thus ensuring that kubelet is still working while other pre-terminate hooks run). This is done + // for v1.31 or above because the kubeadm ControlPlaneKubeletLocalMode was introduced with kubeadm 1.31 (graduated to GA in 1.36). + // This feature configures the kubelet to communicate with the local apiserver. Only because of that the kubelet immediately + // starts failing after the etcd member is removed. We need the ControlPlaneKubeletLocalMode feature with 1.31+ to adhere to the kubelet skew policy. PreTerminateDeleteHookAnnotationPrefix = "pre-terminate.delete.hook.machine.cluster.x-k8s.io" // MachineCertificatesExpiryDateAnnotation annotation specifies the expiry date of the machine certificates in RFC3339 format. @@ -87,6 +87,17 @@ const ( // ManagedNodeAnnotationDomain is one of the CAPI managed Node annotation domains. ManagedNodeAnnotationDomain = "node.cluster.x-k8s.io" + + // PendingAcknowledgeMoveAnnotation is an internal annotation added by the MS controller to a machine when being + // moved from the oldMS to the newMS. The annotation is removed as soon as the MS controller get the acknowledgment about the + // replica being accounted from the corresponding MD. + // Note: The annotation is added when reconciling the oldMS, and it is removed when reconciling the newMS. + // Note: This annotation is used in pair with AcknowledgedMoveAnnotation on MachineSets. + PendingAcknowledgeMoveAnnotation = "in-place-updates.internal.cluster.x-k8s.io/pending-acknowledge-move" + + // UpdateInProgressAnnotation is an internal annotation added to machines by the controller owning the Machine when in-place update + // is started, e.g. by the MachineSet controller; the annotation will be removed by the Machine controller when in-place update is completed. + UpdateInProgressAnnotation = "in-place-updates.internal.cluster.x-k8s.io/update-in-progress" ) // Machine's Available condition and corresponding reasons. @@ -109,7 +120,7 @@ const ( // Machine's Ready condition and corresponding reasons. const ( // MachineReadyCondition is true if the Machine's deletionTimestamp is not set, Machine's BootstrapConfigReady, InfrastructureReady, - // NodeHealthy and HealthCheckSucceeded (if present) conditions are true; if other conditions are defined in spec.readinessGates, + // NodeHealthy and HealthCheckSucceeded (if present) conditions are true, Updating condition is false; if other conditions are defined in spec.readinessGates, // these conditions must be true as well. // Note: // - When summarizing the Deleting condition: @@ -151,6 +162,28 @@ const ( // MachineNotUpToDateReason surface when a Machine spec does not match the spec of the Machine's owner resource, e.g. KubeadmControlPlane or MachineDeployment. MachineNotUpToDateReason = "NotUpToDate" + + // MachineUpToDateUpdatingReason surface when a Machine spec matches the spec of the Machine's owner resource, + // but the Machine is still updating in-place. + MachineUpToDateUpdatingReason = "Updating" +) + +// Machine's Updating condition and corresponding reasons. +// Note: Updating condition is set by the Machine controller during in-place updates. +const ( + // MachineUpdatingCondition is true while an in-place update is in progress on the Machine. + // The condition is owned by the Machine controller and is used to track the progress of in-place updates. + // This condition is considered when computing the UpToDate condition. + MachineUpdatingCondition = "Updating" + + // MachineNotUpdatingReason surfaces when the Machine is not performing an in-place update. + MachineNotUpdatingReason = "NotUpdating" + + // MachineInPlaceUpdatingReason surfaces when the Machine is waiting for in-place update to complete. + MachineInPlaceUpdatingReason = "InPlaceUpdating" + + // MachineInPlaceUpdateFailedReason surfaces when the in-place update has failed. + MachineInPlaceUpdateFailedReason = "InPlaceUpdateFailed" ) // Machine's BootstrapConfigReady condition and corresponding reasons. @@ -276,6 +309,10 @@ const ( // defined by a MachineHealthCheck object. MachineHealthCheckUnhealthyNodeReason = "UnhealthyNode" + // MachineHealthCheckUnhealthyMachineReason surfaces when the machine does not pass the health checks + // defined by a MachineHealthCheck object. + MachineHealthCheckUnhealthyMachineReason = "UnhealthyMachine" + // MachineHealthCheckNodeStartupTimeoutReason surfaces when the node hosted on the machine does not appear within // the timeout defined by a MachineHealthCheck object. MachineHealthCheckNodeStartupTimeoutReason = "NodeStartupTimeout" @@ -451,6 +488,23 @@ type MachineSpec struct { // deletion contains configuration options for Machine deletion. // +optional Deletion MachineDeletionSpec `json:"deletion,omitempty,omitzero"` + + // taints are the node taints that Cluster API will manage. + // This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes, + // e.g. the node controller might add the node.kubernetes.io/not-ready taint. + // Only those taints defined in this list will be added or removed by core Cluster API controllers. + // + // There can be at most 64 taints. + // A pod would have to tolerate all existing taints to run on the corresponding node. + // + // NOTE: This list is implemented as a "map" type, meaning that individual elements can be managed by different owners. + // +optional + // +listType=map + // +listMapKey=key + // +listMapKey=effect + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=64 + Taints []MachineTaint `json:"taints,omitempty"` } // MachineDeletionSpec contains configuration options for Machine deletion. @@ -502,7 +556,7 @@ type MachineReadinessGate struct { type MachineStatus struct { // conditions represents the observations of a Machine's current state. // Known condition types are Available, Ready, UpToDate, BootstrapConfigReady, InfrastructureReady, NodeReady, - // NodeHealthy, Deleting, Paused. + // NodeHealthy, Updating, Deleting, Paused. // If a MachineHealthCheck is targeting this machine, also HealthCheckSucceeded, OwnerRemediated conditions are added. // Additionally control plane Machines controlled by KubeadmControlPlane will have following additional conditions: // APIServerPodHealthy, ControllerManagerPodHealthy, SchedulerPodHealthy, EtcdPodHealthy, EtcdMemberHealthy. @@ -537,7 +591,7 @@ type MachineStatus struct { // phase represents the current phase of machine actuation. // +optional - // +kubebuilder:validation:Enum=Pending;Provisioning;Provisioned;Running;Deleting;Deleted;Failed;Unknown + // +kubebuilder:validation:Enum=Pending;Provisioning;Provisioned;Running;Updating;Deleting;Deleted;Failed;Unknown Phase string `json:"phase,omitempty"` // certificatesExpiryDate is the expiry date of the machine certificates. @@ -695,6 +749,7 @@ func (m *MachineStatus) GetTypedPhase() MachinePhase { MachinePhaseProvisioning, MachinePhaseProvisioned, MachinePhaseRunning, + MachinePhaseUpdating, MachinePhaseDeleting, MachinePhaseDeleted, MachinePhaseFailed: diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machinehealthcheck_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machinehealthcheck_types.go index 9a7e31cae4..9a1f66bc8b 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machinehealthcheck_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machinehealthcheck_types.go @@ -111,6 +111,16 @@ type MachineHealthCheckChecks struct { // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a machine is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the machine is unhealthy. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` } // MachineHealthCheckRemediation configures if and how remediations are triggered if a Machine is unhealthy. @@ -227,7 +237,33 @@ type UnhealthyNodeCondition struct { // timeoutSeconds is the duration that a node must be in a given status for, // after which the node is considered unhealthy. - // For example, with a value of "1h", the node must match the status + // For example, with a value of "3600", the node must match the status + // for at least 1 hour before being considered unhealthy. + // +required + // +kubebuilder:validation:Minimum=0 + TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"` +} + +// UnhealthyMachineCondition represents a Machine condition type and value with a timeout +// specified as a duration. When the named condition has been in the given +// status for at least the timeout value, a machine is considered unhealthy. +type UnhealthyMachineCondition struct { + // type of Machine condition + // +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=316 + // +kubebuilder:validation:XValidation:rule="!(self in ['Ready','Available','HealthCheckSucceeded','OwnerRemediated','ExternallyRemediated'])",message="type must not be one of: Ready, Available, HealthCheckSucceeded, OwnerRemediated, ExternallyRemediated" + // +required + Type string `json:"type,omitempty"` + + // status of the condition, one of True, False, Unknown. + // +required + // +kubebuilder:validation:Enum=True;False;Unknown + Status metav1.ConditionStatus `json:"status,omitempty"` + + // timeoutSeconds is the duration that a machine must be in a given status for, + // after which the machine is considered unhealthy. + // For example, with a value of "3600", the machine must match the status // for at least 1 hour before being considered unhealthy. // +required // +kubebuilder:validation:Minimum=0 diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machineset_types.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machineset_types.go index 8a5a92db7d..80cb19d362 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machineset_types.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/machineset_types.go @@ -33,6 +33,29 @@ const ( // MachineSetFinalizer is the finalizer used by the MachineSet controller to // ensure ordered cleanup of corresponding Machines when a Machineset is being deleted. MachineSetFinalizer = "cluster.x-k8s.io/machineset" + + // MachineSetMoveMachinesToMachineSetAnnotation is an internal annotation added by the MD controller to the oldMS + // when it should scale down by moving machines that can be updated in-place to the newMS instead of deleting them. + // The annotation value is the newMS name. + // Note: This annotation is used in pair with MachineSetReceiveMachinesFromMachineSetsAnnotation to perform a two-ways check before moving a machine from oldMS to newMS: + // + // "oldMS must have: move to newMS" and "newMS must have: receive replicas from oldMS" + MachineSetMoveMachinesToMachineSetAnnotation = "in-place-updates.internal.cluster.x-k8s.io/move-machines-to-machineset" + + // MachineSetReceiveMachinesFromMachineSetsAnnotation is an internal annotation added by the MD controller to the newMS + // when it should receive replicas from oldMSs as a first step of an in-place update operation + // The annotation value is a comma separated list of oldMSs. + // Note: This annotation is used in pair with MachineSetMoveMachinesToMachineSetAnnotation to perform a two-ways check before moving a machine from oldMS to newMS: + // + // "oldMS must have: move to newMS" and "newMS must have: receive replicas from oldMS" + MachineSetReceiveMachinesFromMachineSetsAnnotation = "in-place-updates.internal.cluster.x-k8s.io/receive-machines-from-machinesets" + + // AcknowledgedMoveAnnotation is an internal annotation with a list of machines added by the MD controller + // to a MachineSet when it acknowledges a machine pending acknowledge after being moved from an oldMS. + // The annotation value is a comma separated list of Machines already acknowledged; a machine is dropped + // from this annotation as soon as pending-acknowledge-move is removed from the machine; the annotation is dropped when empty. + // Note: This annotation is used in pair with PendingAcknowledgeMoveAnnotation on Machines. + AcknowledgedMoveAnnotation = "in-place-updates.internal.cluster.x-k8s.io/acknowledged-move" ) // MachineSetSpec defines the desired state of MachineSet. diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/v1beta1_condition_consts.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/v1beta1_condition_consts.go index aef565c0aa..b619c6e0d7 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/v1beta1_condition_consts.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/v1beta1_condition_consts.go @@ -157,6 +157,11 @@ const ( // UnhealthyNodeConditionV1Beta1Reason is the reason used when a machine's node has one of the MachineHealthCheck's unhealthy conditions. UnhealthyNodeConditionV1Beta1Reason = "UnhealthyNode" + + // UnhealthyMachineConditionV1Beta1Reason is the reason used when a machine has one of the MachineHealthCheck's unhealthy conditions. + // When both machine and node issues are detected, this reason takes precedence over node-related reasons + // (NodeNotFoundV1Beta1Reason, NodeStartupTimeoutV1Beta1Reason, UnhealthyNodeConditionV1Beta1Reason). + UnhealthyMachineConditionV1Beta1Reason = "UnhealthyMachine" ) const ( @@ -295,17 +300,27 @@ const ( // failing due to an error. TopologyReconcileFailedV1Beta1Reason = "TopologyReconcileFailed" + // TopologyReconciledClusterCreatingV1Beta1Reason documents reconciliation of a Cluster topology + // not yet created because the BeforeClusterCreate hook is blocking. + TopologyReconciledClusterCreatingV1Beta1Reason = "ClusterCreating" + // TopologyReconciledControlPlaneUpgradePendingV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology // not yet completed because Control Plane is not yet updated to match the desired topology spec. + // + // Deprecated: please use ClusterUpgrading instead. TopologyReconciledControlPlaneUpgradePendingV1Beta1Reason = "ControlPlaneUpgradePending" // TopologyReconciledMachineDeploymentsCreatePendingV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology // not yet completed because at least one of the MachineDeployments is yet to be created. // This generally happens because new MachineDeployment creations are held off while the ControlPlane is not stable. + // + // Deprecated: please use ClusterUpgrading instead. TopologyReconciledMachineDeploymentsCreatePendingV1Beta1Reason = "MachineDeploymentsCreatePending" // TopologyReconciledMachineDeploymentsUpgradePendingV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology // not yet completed because at least one of the MachineDeployments is not yet updated to match the desired topology spec. + // + // Deprecated: please use ClusterUpgrading instead. TopologyReconciledMachineDeploymentsUpgradePendingV1Beta1Reason = "MachineDeploymentsUpgradePending" // TopologyReconciledMachineDeploymentsUpgradeDeferredV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology @@ -314,11 +329,15 @@ const ( // TopologyReconciledMachinePoolsUpgradePendingV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology // not yet completed because at least one of the MachinePools is not yet updated to match the desired topology spec. + // + // Deprecated: please use ClusterUpgrading instead. TopologyReconciledMachinePoolsUpgradePendingV1Beta1Reason = "MachinePoolsUpgradePending" // TopologyReconciledMachinePoolsCreatePendingV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology // not yet completed because at least one of the MachinePools is yet to be created. // This generally happens because new MachinePool creations are held off while the ControlPlane is not stable. + // + // Deprecated: please use ClusterUpgrading instead. TopologyReconciledMachinePoolsCreatePendingV1Beta1Reason = "MachinePoolsCreatePending" // TopologyReconciledMachinePoolsUpgradeDeferredV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology @@ -327,8 +346,14 @@ const ( // TopologyReconciledHookBlockingV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology // not yet completed because at least one of the lifecycle hooks is blocking. + // + // Deprecated: please use ClusterUpgrading instead. TopologyReconciledHookBlockingV1Beta1Reason = "LifecycleHookBlocking" + // TopologyReconciledClusterUpgradingV1Beta1Reason documents reconciliation of a Cluster topology + // not yet completed because a cluster upgrade is still in progress. + TopologyReconciledClusterUpgradingV1Beta1Reason = "ClusterUpgrading" + // TopologyReconciledClusterClassNotReconciledV1Beta1Reason (Severity=Info) documents reconciliation of a Cluster topology not // yet completed because the ClusterClass has not reconciled yet. If this condition persists there may be an issue // with the ClusterClass surfaced in the ClusterClass status or controller logs. diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.deepcopy.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.deepcopy.go index 49d1f66552..5adb8a56c4 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.deepcopy.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.deepcopy.go @@ -253,6 +253,12 @@ func (in *ClusterClassSpec) DeepCopyInto(out *ClusterClassSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + out.Upgrade = in.Upgrade + if in.KubernetesVersions != nil { + in, out := &in.KubernetesVersions, &out.KubernetesVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClassSpec. @@ -363,6 +369,37 @@ func (in *ClusterClassTemplateReference) DeepCopy() *ClusterClassTemplateReferen return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClassUpgrade) DeepCopyInto(out *ClusterClassUpgrade) { + *out = *in + out.External = in.External +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClassUpgrade. +func (in *ClusterClassUpgrade) DeepCopy() *ClusterClassUpgrade { + if in == nil { + return nil + } + out := new(ClusterClassUpgrade) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClassUpgradeExternal) DeepCopyInto(out *ClusterClassUpgradeExternal) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClassUpgradeExternal. +func (in *ClusterClassUpgradeExternal) DeepCopy() *ClusterClassUpgradeExternal { + if in == nil { + return nil + } + out := new(ClusterClassUpgradeExternal) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterClassV1Beta1DeprecatedStatus) DeepCopyInto(out *ClusterClassV1Beta1DeprecatedStatus) { *out = *in @@ -803,6 +840,13 @@ func (in *ControlPlaneClassHealthCheckChecks) DeepCopyInto(out *ControlPlaneClas (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneClassHealthCheckChecks. @@ -979,6 +1023,13 @@ func (in *ControlPlaneTopologyHealthCheckChecks) DeepCopyInto(out *ControlPlaneT (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneTopologyHealthCheckChecks. @@ -1567,6 +1618,13 @@ func (in *MachineDeploymentClassHealthCheckChecks) DeepCopyInto(out *MachineDepl (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentClassHealthCheckChecks. @@ -2034,6 +2092,13 @@ func (in *MachineDeploymentTopologyHealthCheckChecks) DeepCopyInto(out *MachineD (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentTopologyHealthCheckChecks. @@ -2439,6 +2504,13 @@ func (in *MachineHealthCheckChecks) DeepCopyInto(out *MachineHealthCheckChecks) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineHealthCheckChecks. @@ -3369,6 +3441,11 @@ func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { copy(*out, *in) } in.Deletion.DeepCopyInto(&out.Deletion) + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]MachineTaint, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSpec. @@ -3427,6 +3504,21 @@ func (in *MachineStatus) DeepCopy() *MachineStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineTaint) DeepCopyInto(out *MachineTaint) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineTaint. +func (in *MachineTaint) DeepCopy() *MachineTaint { + if in == nil { + return nil + } + out := new(MachineTaint) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineTemplateSpec) DeepCopyInto(out *MachineTemplateSpec) { *out = *in @@ -3664,6 +3756,26 @@ func (in *Topology) DeepCopy() *Topology { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UnhealthyMachineCondition) DeepCopyInto(out *UnhealthyMachineCondition) { + *out = *in + if in.TimeoutSeconds != nil { + in, out := &in.TimeoutSeconds, &out.TimeoutSeconds + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnhealthyMachineCondition. +func (in *UnhealthyMachineCondition) DeepCopy() *UnhealthyMachineCondition { + if in == nil { + return nil + } + out := new(UnhealthyMachineCondition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UnhealthyNodeCondition) DeepCopyInto(out *UnhealthyNodeCondition) { *out = *in diff --git a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.openapi.go b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.openapi.go index 6ada26c78c..6eecc0d326 100644 --- a/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.openapi.go +++ b/vendor/sigs.k8s.io/cluster-api/api/core/v1beta2/zz_generated.openapi.go @@ -42,6 +42,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassStatusVariable": schema_cluster_api_api_core_v1beta2_ClusterClassStatusVariable(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassStatusVariableDefinition": schema_cluster_api_api_core_v1beta2_ClusterClassStatusVariableDefinition(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference": schema_cluster_api_api_core_v1beta2_ClusterClassTemplateReference(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassUpgrade": schema_cluster_api_api_core_v1beta2_ClusterClassUpgrade(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassUpgradeExternal": schema_cluster_api_api_core_v1beta2_ClusterClassUpgradeExternal(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassV1Beta1DeprecatedStatus": schema_cluster_api_api_core_v1beta2_ClusterClassV1Beta1DeprecatedStatus(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassVariable": schema_cluster_api_api_core_v1beta2_ClusterClassVariable(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassVariableMetadata": schema_cluster_api_api_core_v1beta2_ClusterClassVariableMetadata(ref), @@ -161,6 +163,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineSetV1Beta1DeprecatedStatus": schema_cluster_api_api_core_v1beta2_MachineSetV1Beta1DeprecatedStatus(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineSpec": schema_cluster_api_api_core_v1beta2_MachineSpec(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineStatus": schema_cluster_api_api_core_v1beta2_MachineStatus(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineTaint": schema_cluster_api_api_core_v1beta2_MachineTaint(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineTemplateSpec": schema_cluster_api_api_core_v1beta2_MachineTemplateSpec(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineV1Beta1DeprecatedStatus": schema_cluster_api_api_core_v1beta2_MachineV1Beta1DeprecatedStatus(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.NetworkRanges": schema_cluster_api_api_core_v1beta2_NetworkRanges(ref), @@ -171,6 +174,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.PatchSelectorMatchMachineDeploymentClass": schema_cluster_api_api_core_v1beta2_PatchSelectorMatchMachineDeploymentClass(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.PatchSelectorMatchMachinePoolClass": schema_cluster_api_api_core_v1beta2_PatchSelectorMatchMachinePoolClass(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.Topology": schema_cluster_api_api_core_v1beta2_Topology(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition": schema_cluster_api_api_core_v1beta2_UnhealthyMachineCondition(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition": schema_cluster_api_api_core_v1beta2_UnhealthyNodeCondition(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ValidationRule": schema_cluster_api_api_core_v1beta2_ValidationRule(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.VariableSchema": schema_cluster_api_api_core_v1beta2_VariableSchema(ref), @@ -617,12 +621,39 @@ func schema_cluster_api_api_core_v1beta2_ClusterClassSpec(ref common.ReferenceCa }, }, }, + "upgrade": { + SchemaProps: spec.SchemaProps{ + Description: "upgrade defines the upgrade configuration for clusters using this ClusterClass.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassUpgrade"), + }, + }, + "kubernetesVersions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "kubernetesVersions is the list of Kubernetes versions that can be used for clusters using this ClusterClass. The list of version must be ordered from the older to the newer version, and there should be at least one version for every minor in between the first and the last version.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, }, Required: []string{"infrastructure", "controlPlane"}, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterAvailabilityGate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassPatch", "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassVariable", "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClass", "sigs.k8s.io/cluster-api/api/core/v1beta2.InfrastructureClass", "sigs.k8s.io/cluster-api/api/core/v1beta2.WorkersClass"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterAvailabilityGate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassPatch", "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassUpgrade", "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassVariable", "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClass", "sigs.k8s.io/cluster-api/api/core/v1beta2.InfrastructureClass", "sigs.k8s.io/cluster-api/api/core/v1beta2.WorkersClass"}, } } @@ -823,6 +854,48 @@ func schema_cluster_api_api_core_v1beta2_ClusterClassTemplateReference(ref commo } } +func schema_cluster_api_api_core_v1beta2_ClusterClassUpgrade(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterClassUpgrade defines the upgrade configuration for clusters using the ClusterClass.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "external": { + SchemaProps: spec.SchemaProps{ + Description: "external defines external runtime extensions for upgrade operations.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassUpgradeExternal"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassUpgradeExternal"}, + } +} + +func schema_cluster_api_api_core_v1beta2_ClusterClassUpgradeExternal(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterClassUpgradeExternal defines external runtime extensions for upgrade operations.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "generateUpgradePlanExtension": { + SchemaProps: spec.SchemaProps{ + Description: "generateUpgradePlanExtension references an extension which is called to generate upgrade plan.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + func schema_cluster_api_api_core_v1beta2_ClusterClassV1Beta1DeprecatedStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1616,11 +1689,30 @@ func schema_cluster_api_api_core_v1beta2_ControlPlaneClassHealthCheckChecks(ref }, }, }, + "unhealthyMachineConditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a machine is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the machine is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -1899,11 +1991,30 @@ func schema_cluster_api_api_core_v1beta2_ControlPlaneTopologyHealthCheckChecks(r }, }, }, + "unhealthyMachineConditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a machine is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the machine is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -2920,11 +3031,30 @@ func schema_cluster_api_api_core_v1beta2_MachineDeploymentClassHealthCheckChecks }, }, }, + "unhealthyMachineConditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a machine is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the machine is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -3700,11 +3830,30 @@ func schema_cluster_api_api_core_v1beta2_MachineDeploymentTopologyHealthCheckChe }, }, }, + "unhealthyMachineConditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a machine is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the machine is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -4332,11 +4481,30 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckChecks(ref common.Ref }, }, }, + "unhealthyMachineConditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a machine is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the machine is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -5996,12 +6164,35 @@ func schema_cluster_api_api_core_v1beta2_MachineSpec(ref common.ReferenceCallbac Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeletionSpec"), }, }, + "taints": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "key", + "effect", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "taints are the node taints that Cluster API will manage. This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes, e.g. the node controller might add the node.kubernetes.io/not-ready taint. Only those taints defined in this list will be added or removed by core Cluster API controllers.\n\nThere can be at most 64 taints. A pod would have to tolerate all existing taints to run on the corresponding node.\n\nNOTE: This list is implemented as a \"map\" type, meaning that individual elements can be managed by different owners.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.MachineTaint"), + }, + }, + }, + }, + }, }, Required: []string{"clusterName", "bootstrap", "infrastructureRef"}, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.Bootstrap", "sigs.k8s.io/cluster-api/api/core/v1beta2.ContractVersionedObjectReference", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeletionSpec", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineReadinessGate"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.Bootstrap", "sigs.k8s.io/cluster-api/api/core/v1beta2.ContractVersionedObjectReference", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeletionSpec", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineReadinessGate", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineTaint"}, } } @@ -6022,7 +6213,7 @@ func schema_cluster_api_api_core_v1beta2_MachineStatus(ref common.ReferenceCallb }, }, SchemaProps: spec.SchemaProps{ - Description: "conditions represents the observations of a Machine's current state. Known condition types are Available, Ready, UpToDate, BootstrapConfigReady, InfrastructureReady, NodeReady, NodeHealthy, Deleting, Paused. If a MachineHealthCheck is targeting this machine, also HealthCheckSucceeded, OwnerRemediated conditions are added. Additionally control plane Machines controlled by KubeadmControlPlane will have following additional conditions: APIServerPodHealthy, ControllerManagerPodHealthy, SchedulerPodHealthy, EtcdPodHealthy, EtcdMemberHealthy.", + Description: "conditions represents the observations of a Machine's current state. Known condition types are Available, Ready, UpToDate, BootstrapConfigReady, InfrastructureReady, NodeReady, NodeHealthy, Updating, Deleting, Paused. If a MachineHealthCheck is targeting this machine, also HealthCheckSucceeded, OwnerRemediated conditions are added. Additionally control plane Machines controlled by KubeadmControlPlane will have following additional conditions: APIServerPodHealthy, ControllerManagerPodHealthy, SchedulerPodHealthy, EtcdPodHealthy, EtcdMemberHealthy.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -6114,6 +6305,48 @@ func schema_cluster_api_api_core_v1beta2_MachineStatus(ref common.ReferenceCallb } } +func schema_cluster_api_api_core_v1beta2_MachineTaint(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MachineTaint defines a taint equivalent to corev1.Taint, but additionally having a propagation field.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "key": { + SchemaProps: spec.SchemaProps{ + Description: "key is the taint key to be applied to a node. Must be a valid qualified name of maximum size 63 characters with an optional subdomain prefix of maximum size 253 characters, separated by a `/`.", + Type: []string{"string"}, + Format: "", + }, + }, + "value": { + SchemaProps: spec.SchemaProps{ + Description: "value is the taint value corresponding to the taint key. It must be a valid label value of maximum size 63 characters.", + Type: []string{"string"}, + Format: "", + }, + }, + "effect": { + SchemaProps: spec.SchemaProps{ + Description: "effect is the effect for the taint. Valid values are NoSchedule, PreferNoSchedule and NoExecute.", + Type: []string{"string"}, + Format: "", + }, + }, + "propagation": { + SchemaProps: spec.SchemaProps{ + Description: "propagation defines how this taint should be propagated to nodes. Valid values are 'Always' and 'OnInitialization'. Always: The taint will be continuously reconciled. If it is not set for a node, it will be added during reconciliation. OnInitialization: The taint will be added during node initialization. If it gets removed from the node later on it will not get added again.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"key", "effect", "propagation"}, + }, + }, + } +} + func schema_cluster_api_api_core_v1beta2_MachineTemplateSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -6518,6 +6751,41 @@ func schema_cluster_api_api_core_v1beta2_Topology(ref common.ReferenceCallback) } } +func schema_cluster_api_api_core_v1beta2_UnhealthyMachineCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "UnhealthyMachineCondition represents a Machine condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a machine is considered unhealthy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "type of Machine condition", + Type: []string{"string"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "status of the condition, one of True, False, Unknown.", + Type: []string{"string"}, + Format: "", + }, + }, + "timeoutSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "timeoutSeconds is the duration that a machine must be in a given status for, after which the machine is considered unhealthy. For example, with a value of \"3600\", the machine must match the status for at least 1 hour before being considered unhealthy.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + Required: []string{"type", "status", "timeoutSeconds"}, + }, + }, + } +} + func schema_cluster_api_api_core_v1beta2_UnhealthyNodeCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -6541,7 +6809,7 @@ func schema_cluster_api_api_core_v1beta2_UnhealthyNodeCondition(ref common.Refer }, "timeoutSeconds": { SchemaProps: spec.SchemaProps{ - Description: "timeoutSeconds is the duration that a node must be in a given status for, after which the node is considered unhealthy. For example, with a value of \"1h\", the node must match the status for at least 1 hour before being considered unhealthy.", + Description: "timeoutSeconds is the duration that a node must be in a given status for, after which the node is considered unhealthy. For example, with a value of \"3600\", the node must match the status for at least 1 hour before being considered unhealthy.", Type: []string{"integer"}, Format: "int32", }, diff --git a/vendor/sigs.k8s.io/cluster-api/feature/feature.go b/vendor/sigs.k8s.io/cluster-api/feature/feature.go index 15a6fb169b..5f5956cdcf 100644 --- a/vendor/sigs.k8s.io/cluster-api/feature/feature.go +++ b/vendor/sigs.k8s.io/cluster-api/feature/feature.go @@ -35,15 +35,6 @@ const ( // beta: v1.7 MachinePool featuregate.Feature = "MachinePool" - // ClusterResourceSet is a feature gate for the ClusterResourceSet functionality. - // - // alpha: v0.3 - // beta: v0.4 - // GA: v1.10 - // - // Deprecated: ClusterResourceSet feature is now GA and the corresponding feature flag will be removed in 1.12 release. - ClusterResourceSet featuregate.Feature = "ClusterResourceSet" - // ClusterTopology is a feature gate for the ClusterClass and managed topologies functionality. // // alpha: v0.4 @@ -77,6 +68,21 @@ const ( // // alpha: v1.10 PriorityQueue featuregate.Feature = "PriorityQueue" + + // ReconcilerRateLimiting is a feature gate that controls if reconcilers are rate-limited. + // Note: Currently the feature gate is rate-limiting to 1 request / 1 second. + // + // alpha: v1.12 + ReconcilerRateLimiting featuregate.Feature = "ReconcilerRateLimiting" + + // InPlaceUpdates is a feature gate for the in-place machine updates functionality. + // alpha: v1.12 + InPlaceUpdates featuregate.Feature = "InPlaceUpdates" + + // MachineTaintPropagation is a feature gate for the machine taint propagation functionality. + // + // alpha: v1.12 + MachineTaintPropagation featuregate.Feature = "MachineTaintPropagation" ) func init() { @@ -87,12 +93,14 @@ func init() { // To add a new feature, define a key for it above and add it here. var defaultClusterAPIFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ // Every feature should be initiated here: - ClusterResourceSet: {Default: true, PreRelease: featuregate.GA}, MachinePool: {Default: true, PreRelease: featuregate.Beta}, MachineSetPreflightChecks: {Default: true, PreRelease: featuregate.Beta}, MachineWaitForVolumeDetachConsiderVolumeAttachments: {Default: true, PreRelease: featuregate.Beta}, PriorityQueue: {Default: false, PreRelease: featuregate.Alpha}, + ReconcilerRateLimiting: {Default: false, PreRelease: featuregate.Alpha}, ClusterTopology: {Default: false, PreRelease: featuregate.Alpha}, KubeadmBootstrapFormatIgnition: {Default: false, PreRelease: featuregate.Alpha}, RuntimeSDK: {Default: false, PreRelease: featuregate.Alpha}, + InPlaceUpdates: {Default: false, PreRelease: featuregate.Alpha}, + MachineTaintPropagation: {Default: false, PreRelease: featuregate.Alpha}, } diff --git a/vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane.go b/vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane.go index 2d4011726a..3d08159b77 100644 --- a/vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane.go +++ b/vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane.go @@ -214,7 +214,7 @@ func (c *ControlPlaneContract) ExternalManagedControlPlane() *Bool { // IsProvisioning returns true if the control plane is being created for the first time. // Returns false, if the control plane was already previously provisioned. func (c *ControlPlaneContract) IsProvisioning(obj *unstructured.Unstructured) (bool, error) { - // We can know if the control plane was previously created or is being cretaed for the first + // We can know if the control plane was previously created or is being created for the first // time by looking at controlplane.status.version. If the version in status is set to a valid // value then the control plane was already provisioned at a previous time. If not, we can // assume that the control plane is being created for the first time. diff --git a/vendor/sigs.k8s.io/cluster-api/util/conditions/sort.go b/vendor/sigs.k8s.io/cluster-api/util/conditions/sort.go index d0be13af9e..d06baeba82 100644 --- a/vendor/sigs.k8s.io/cluster-api/util/conditions/sort.go +++ b/vendor/sigs.k8s.io/cluster-api/util/conditions/sort.go @@ -76,6 +76,7 @@ func defaultSortLessFunc(i, j metav1.Condition) bool { // | OwnerRemediated | | | | | | x | // | -- Operations -- | | | | | | | // | TopologyReconciled | x | | | | | | +// | Updating | | | | | | x | // | RollingOut | x | x | x | | x | | // | Remediating | x | x | x | x | x | | // | ScalingDown | x | x | x | x | x | | @@ -117,6 +118,7 @@ var order = []string{ clusterv1.MachineHealthCheckSucceededCondition, clusterv1.MachineOwnerRemediatedCondition, clusterv1.ClusterTopologyReconciledCondition, + clusterv1.MachineUpdatingCondition, clusterv1.RollingOutCondition, clusterv1.RemediatingCondition, clusterv1.ScalingDownCondition, diff --git a/vendor/sigs.k8s.io/cluster-api/util/util.go b/vendor/sigs.k8s.io/cluster-api/util/util.go index 684ef3d07b..992d574dde 100644 --- a/vendor/sigs.k8s.io/cluster-api/util/util.go +++ b/vendor/sigs.k8s.io/cluster-api/util/util.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -179,7 +180,7 @@ func GetClusterByName(ctx context.Context, c client.Client, namespace, name stri } if err := c.Get(ctx, key, cluster); err != nil { - return nil, errors.Wrapf(err, "failed to get Cluster/%s", name) + return nil, errors.Wrapf(err, "failed to get Cluster %s", klog.KRef(namespace, name)) } return cluster, nil @@ -359,9 +360,9 @@ func indexOwnerRef(ownerReferences []metav1.OwnerReference, ref metav1.OwnerRefe // IsOwnedByObject returns true if any of the owner references point to the given target. // It matches the object based on the Group, Kind and Name. -func IsOwnedByObject(obj metav1.Object, target client.Object) bool { +func IsOwnedByObject(obj metav1.Object, target client.Object, targetGK schema.GroupKind) bool { for _, ref := range obj.GetOwnerReferences() { - if refersTo(&ref, target) { + if refersTo(&ref, target, targetGK) { return true } } @@ -369,12 +370,12 @@ func IsOwnedByObject(obj metav1.Object, target client.Object) bool { } // IsControlledBy differs from metav1.IsControlledBy. This function matches on Group, Kind and Name. The metav1.IsControlledBy function matches on UID only. -func IsControlledBy(obj metav1.Object, owner client.Object) bool { +func IsControlledBy(obj metav1.Object, owner client.Object, ownerGK schema.GroupKind) bool { controllerRef := metav1.GetControllerOfNoCopy(obj) if controllerRef == nil { return false } - return refersTo(controllerRef, owner) + return refersTo(controllerRef, owner, ownerGK) } // Returns true if a and b point to the same object based on Group, Kind and Name. @@ -393,14 +394,13 @@ func referSameObject(a, b metav1.OwnerReference) bool { } // Returns true if ref refers to obj based on Group, Kind and Name. -func refersTo(ref *metav1.OwnerReference, obj client.Object) bool { +func refersTo(ref *metav1.OwnerReference, obj client.Object, objGK schema.GroupKind) bool { refGv, err := schema.ParseGroupVersion(ref.APIVersion) if err != nil { return false } - gvk := obj.GetObjectKind().GroupVersionKind() - return refGv.Group == gvk.Group && ref.Kind == gvk.Kind && ref.Name == obj.GetName() + return refGv.Group == objGK.Group && ref.Kind == objGK.Kind && ref.Name == obj.GetName() } // UnstructuredUnmarshalField is a wrapper around json and unstructured objects to decode and copy a specific field @@ -690,6 +690,8 @@ func IsSupportedVersionSkew(a, b semver.Version) bool { // LowestNonZeroResult compares two reconciliation results // and returns the one with lowest requeue time. +// +//nolint:staticcheck // SA1019: Requeue is deprecated. func LowestNonZeroResult(i, j ctrl.Result) ctrl.Result { switch { case i.IsZero(): @@ -751,3 +753,89 @@ func MergeMap(maps ...map[string]string) map[string]string { } return m } + +// GetOwnerMachinePool returns the MachinePool objects owning the current resource. +func GetOwnerMachinePool(ctx context.Context, c client.Client, obj metav1.ObjectMeta) (*clusterv1.MachinePool, error) { + for _, ref := range obj.GetOwnerReferences() { + if ref.Kind != "MachinePool" { + continue + } + gv, err := schema.ParseGroupVersion(ref.APIVersion) + if err != nil { + return nil, errors.WithStack(err) + } + if gv.Group == clusterv1.GroupVersion.Group { + return GetMachinePoolByName(ctx, c, obj.Namespace, ref.Name) + } + } + return nil, nil +} + +// GetMachinePoolByName finds and returns a MachinePool object using the specified params. +func GetMachinePoolByName(ctx context.Context, c client.Client, namespace, name string) (*clusterv1.MachinePool, error) { + m := &clusterv1.MachinePool{} + key := client.ObjectKey{Name: name, Namespace: namespace} + if err := c.Get(ctx, key, m); err != nil { + return nil, err + } + return m, nil +} + +// GetMachinePoolByLabels finds and returns a MachinePool object using the value of clusterv1.MachinePoolNameLabel. +// This differs from GetMachinePoolByName as the label value can be a hash. +func GetMachinePoolByLabels(ctx context.Context, c client.Client, namespace string, labels map[string]string) (*clusterv1.MachinePool, error) { + selector := map[string]string{} + if clusterName, ok := labels[clusterv1.ClusterNameLabel]; ok { + selector = map[string]string{clusterv1.ClusterNameLabel: clusterName} + } + + if poolNameHash, ok := labels[clusterv1.MachinePoolNameLabel]; ok { + machinePoolList := &clusterv1.MachinePoolList{} + if err := c.List(ctx, machinePoolList, client.InNamespace(namespace), client.MatchingLabels(selector)); err != nil { + return nil, errors.Wrapf(err, "failed to list MachinePools using labels %v", selector) + } + + for _, mp := range machinePoolList.Items { + if format.MustFormatValue(mp.Name) == poolNameHash { + return &mp, nil + } + } + } else { + return nil, errors.Errorf("labels missing required key `%s`", clusterv1.MachinePoolNameLabel) + } + + return nil, nil +} + +// MachinePoolToInfrastructureMapFunc returns a handler.MapFunc that watches for +// MachinePool events and returns reconciliation requests for an infrastructure provider object. +func MachinePoolToInfrastructureMapFunc(ctx context.Context, gvk schema.GroupVersionKind) handler.MapFunc { + log := ctrl.LoggerFrom(ctx) + return func(_ context.Context, o client.Object) []reconcile.Request { + m, ok := o.(*clusterv1.MachinePool) + if !ok { + log.V(4).Info("Not a machine pool", "Object", klog.KObj(o)) + return nil + } + log := log.WithValues("MachinePool", klog.KObj(o)) + + gk := gvk.GroupKind() + ref := m.Spec.Template.Spec.InfrastructureRef + // Return early if the GroupKind doesn't match what we expect. + infraGK := ref.GroupKind() + if gk != infraGK { + log.V(4).Info("Infra kind doesn't match filter group kind", "infrastructureGroupKind", infraGK.String()) + return nil + } + + log.V(4).Info("Projecting object") + return []reconcile.Request{ + { + NamespacedName: client.ObjectKey{ + Namespace: m.Namespace, + Name: ref.Name, + }, + }, + } + } +} diff --git a/vendor/sigs.k8s.io/cluster-api/util/version/version.go b/vendor/sigs.k8s.io/cluster-api/util/version/version.go index 0e5210b349..132b71ed5d 100644 --- a/vendor/sigs.k8s.io/cluster-api/util/version/version.go +++ b/vendor/sigs.k8s.io/cluster-api/util/version/version.go @@ -130,7 +130,7 @@ func (v buildIdentifiers) compare(o buildIdentifiers) int { } // if everything is equal till now the longer is greater - if i == len(v) && i == len(o) { //nolint: gocritic + if i == len(v) && i == len(o) { return 0 } else if i == len(v) && i < len(o) { return -1